Merge "Prevent monkey from triggering bugreport" into lmp-dev
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index 0567500..b8575d7 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -80,17 +80,17 @@
mFiles = files;
mKeys = keys;
- WallpaperManager wpm;
- wpm = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
- mDesiredMinWidth = (double) wpm.getDesiredMinimumWidth();
+ final WindowManager wm =
+ (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ final WallpaperManager wpm =
+ (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
+ final Display d = wm.getDefaultDisplay();
+ final Point size = new Point();
+ d.getSize(size);
+ mDesiredMinWidth = size.x;
mDesiredMinHeight = (double) wpm.getDesiredMinimumHeight();
- if (mDesiredMinWidth <= 0 || mDesiredMinHeight <= 0) {
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display d = wm.getDefaultDisplay();
- Point size = new Point();
- d.getSize(size);
- mDesiredMinWidth = size.x;
+ if (mDesiredMinHeight <= 0) {
mDesiredMinHeight = size.y;
}
@@ -130,15 +130,12 @@
if (DEBUG) Slog.d(TAG, "Restoring wallpaper image w=" + options.outWidth
+ " h=" + options.outHeight);
- // How much does the image differ from our preference? The threshold
- // here is set to accept any image larger than our target, because
- // scaling down is acceptable; but to reject images that are deemed
- // "too small" to scale up attractively. The value 1.33 is just barely
- // too low to pass Nexus 1 or Droid wallpapers for use on a Xoom, but
- // will pass anything relatively larger.
- double widthRatio = mDesiredMinWidth / options.outWidth;
- double heightRatio = mDesiredMinHeight / options.outHeight;
- if (widthRatio > 0 && widthRatio < 1.33
+ // We accept any wallpaper that is at least as wide as our preference
+ // (i.e. wide enough to fill the screen), and is within a comfortable
+ // factor of the target height, to avoid significant clipping/scaling/
+ // letterboxing.
+ final double heightRatio = mDesiredMinHeight / options.outHeight;
+ if (options.outWidth >= mDesiredMinWidth
&& heightRatio > 0 && heightRatio < 1.33) {
// sufficiently close to our resolution; go ahead and use it
Slog.d(TAG, "Applying restored wallpaper image.");
@@ -147,8 +144,11 @@
// since it does not exist anywhere other than the private wallpaper
// file.
} else {
- Slog.i(TAG, "Dimensions too far off; using default wallpaper. wr=" + widthRatio
- + " hr=" + heightRatio);
+ Slog.i(TAG, "Restored image dimensions (w="
+ + options.outWidth + ", h=" + options.outHeight
+ + ") too far off target (tw="
+ + mDesiredMinWidth + ", th=" + mDesiredMinHeight
+ + "); falling back to default wallpaper.");
f.delete();
}
}
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index d19604b..0cafff8 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -78,7 +78,7 @@
* can use the convenience method {@link Item#coerceToText Item.coerceToText}.
* In this case there is generally no need to worry about the MIME types
* reported by {@link ClipDescription#getMimeType(int) getDescription().getMimeType(int)},
- * since any clip item an always be converted to a string.
+ * since any clip item can always be converted to a string.
*
* <p>More complicated exchanges will be done through URIs, in particular
* "content:" URIs. A content URI allows the recipient of a ClippedData item
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index 1a8ea47..8487dae 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -150,7 +150,7 @@
* numbers.
* <p>
* Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
- * this method will accept leading slash in the path.
+ * this method will accept a leading slash in the path.
*
* @param authority the authority to match
* @param path the path to match. * may be used as a wild card for
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2e24785..9194ca8 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -25,6 +25,7 @@
import android.net.NetworkUtils;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -2147,50 +2148,57 @@
Log.d(TAG, "CM callback handler got msg " + message.what);
switch (message.what) {
case CALLBACK_PRECHECK: {
- NetworkRequest request = getNetworkRequest(message);
+ NetworkRequest request = (NetworkRequest)getObject(message,
+ NetworkRequest.class);
NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onPreCheck(getNetwork(message));
+ callbacks.onPreCheck((Network)getObject(message, Network.class));
} else {
Log.e(TAG, "callback not found for PRECHECK message");
}
break;
}
case CALLBACK_AVAILABLE: {
- NetworkRequest request = getNetworkRequest(message);
+ NetworkRequest request = (NetworkRequest)getObject(message,
+ NetworkRequest.class);
NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onAvailable(getNetwork(message));
+ callbacks.onAvailable((Network)getObject(message, Network.class));
} else {
Log.e(TAG, "callback not found for AVAILABLE message");
}
break;
}
case CALLBACK_LOSING: {
- NetworkRequest request = getNetworkRequest(message);
+ NetworkRequest request = (NetworkRequest)getObject(message,
+ NetworkRequest.class);
NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onLosing(getNetwork(message), message.arg1);
+ callbacks.onLosing((Network)getObject(message, Network.class),
+ message.arg1);
} else {
Log.e(TAG, "callback not found for LOSING message");
}
break;
}
case CALLBACK_LOST: {
- NetworkRequest request = getNetworkRequest(message);
+ NetworkRequest request = (NetworkRequest)getObject(message,
+ NetworkRequest.class);
+
NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- callbacks.onLost(getNetwork(message));
+ callbacks.onLost((Network)getObject(message, Network.class));
} else {
Log.e(TAG, "callback not found for LOST message");
}
break;
}
case CALLBACK_UNAVAIL: {
- NetworkRequest req = (NetworkRequest)message.obj;
+ NetworkRequest request = (NetworkRequest)getObject(message,
+ NetworkRequest.class);
NetworkCallback callbacks = null;
synchronized(mCallbackMap) {
- callbacks = mCallbackMap.get(req);
+ callbacks = mCallbackMap.get(request);
}
if (callbacks != null) {
callbacks.onUnavailable();
@@ -2200,33 +2208,37 @@
break;
}
case CALLBACK_CAP_CHANGED: {
- NetworkRequest request = getNetworkRequest(message);
+ NetworkRequest request = (NetworkRequest)getObject(message,
+ NetworkRequest.class);
NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- Network network = getNetwork(message);
- NetworkCapabilities cap = mCm.getNetworkCapabilities(network);
+ Network network = (Network)getObject(message, Network.class);
+ NetworkCapabilities cap = (NetworkCapabilities)getObject(message,
+ NetworkCapabilities.class);
callbacks.onCapabilitiesChanged(network, cap);
} else {
- Log.e(TAG, "callback not found for CHANGED message");
+ Log.e(TAG, "callback not found for CAP_CHANGED message");
}
break;
}
case CALLBACK_IP_CHANGED: {
- NetworkRequest request = getNetworkRequest(message);
+ NetworkRequest request = (NetworkRequest)getObject(message,
+ NetworkRequest.class);
NetworkCallback callbacks = getCallbacks(request);
if (callbacks != null) {
- Network network = getNetwork(message);
- LinkProperties lp = mCm.getLinkProperties(network);
+ Network network = (Network)getObject(message, Network.class);
+ LinkProperties lp = (LinkProperties)getObject(message,
+ LinkProperties.class);
callbacks.onLinkPropertiesChanged(network, lp);
} else {
- Log.e(TAG, "callback not found for CHANGED message");
+ Log.e(TAG, "callback not found for IP_CHANGED message");
}
break;
}
case CALLBACK_RELEASED: {
- NetworkRequest req = (NetworkRequest)message.obj;
+ NetworkRequest req = (NetworkRequest)getObject(message, NetworkRequest.class);
NetworkCallback callbacks = null;
synchronized(mCallbackMap) {
callbacks = mCallbackMap.remove(req);
@@ -2254,23 +2266,14 @@
}
}
- private NetworkRequest getNetworkRequest(Message msg) {
- return (NetworkRequest)(msg.obj);
+ private Object getObject(Message msg, Class c) {
+ return msg.getData().getParcelable(c.getSimpleName());
}
private NetworkCallback getCallbacks(NetworkRequest req) {
synchronized(mCallbackMap) {
return mCallbackMap.get(req);
}
}
- private Network getNetwork(Message msg) {
- return new Network(msg.arg2);
- }
- private NetworkCallback removeCallbacks(Message msg) {
- NetworkRequest req = (NetworkRequest)msg.obj;
- synchronized(mCallbackMap) {
- return mCallbackMap.remove(req);
- }
- }
}
private void incCallbackHandlerRefCount() {
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index ce70455..2099c3f 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -151,7 +151,7 @@
}
/**
- * Returns true if this URI is relative, i.e. if it doesn't contain an
+ * Returns true if this URI is relative, i.e. if it doesn't contain an
* explicit scheme.
*
* @return true if this URI is relative, false if it's absolute
@@ -159,7 +159,7 @@
public abstract boolean isRelative();
/**
- * Returns true if this URI is absolute, i.e. if it contains an
+ * Returns true if this URI is absolute, i.e. if it contains an
* explicit scheme.
*
* @return true if this URI is absolute, false if it's relative
@@ -176,8 +176,8 @@
public abstract String getScheme();
/**
- * Gets the scheme-specific part of this URI, i.e. everything between the
- * scheme separator ':' and the fragment separator '#'. If this is a
+ * Gets the scheme-specific part of this URI, i.e. everything between
+ * the scheme separator ':' and the fragment separator '#'. If this is a
* relative URI, this method returns the entire URI. Decodes escaped octets.
*
* <p>Example: "//www.google.com/search?q=android"
@@ -187,8 +187,8 @@
public abstract String getSchemeSpecificPart();
/**
- * Gets the scheme-specific part of this URI, i.e. everything between the
- * scheme separator ':' and the fragment separator '#'. If this is a
+ * Gets the scheme-specific part of this URI, i.e. everything between
+ * the scheme separator ':' and the fragment separator '#'. If this is a
* relative URI, this method returns the entire URI. Leaves escaped octets
* intact.
*
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index fca15ac..16250c7 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -395,7 +395,7 @@
void setDefaultNetId(int netId);
void clearDefaultNetId();
- void setPermission(boolean internal, boolean changeNetState, in int[] uids);
+ void setPermission(String permission, in int[] uids);
void clearPermission(in int[] uids);
/**
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 0ee8d86f..47ea732 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1725,7 +1725,7 @@
for (int i = 0; i < numViolations; ++i) {
if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
- if (info.crashInfo.stackTrace.length() > 10000) {
+ if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 10000) {
// 10000 characters is way too large for this to be any sane kind of
// strict mode collection of stacks. We've had a problem where we leave
// strict mode violations associated with the thread, and it keeps tacking
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 2315c74..37294e7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -430,10 +430,14 @@
}
}
- /**
+ /**
* Used to determine whether the user making this call is subject to
* teleportations.
- * @return whether the user making this call is a goat
+ *
+ * <p>As of {@link android.os.Build.VERSION_CODES#L}, this method can
+ * now automatically identify goats using advanced goat recognition technology.</p>
+ *
+ * @return Returns true if the user making this call is a goat.
*/
public boolean isUserAGoat() {
return mContext.getPackageManager()
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 45eb0bf..dcdbba78 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -28,6 +28,8 @@
import android.os.RemoteException;
import android.util.Log;
+import java.lang.ref.WeakReference;
+
/**
* This class provides a base class for recognition service implementations. This class should be
* extended only in case you wish to implement a new speech recognizer. Please note that the
@@ -315,40 +317,46 @@
}
/** Binder of the recognition service */
- private static class RecognitionServiceBinder extends IRecognitionService.Stub {
- private RecognitionService mInternalService;
+ private static final class RecognitionServiceBinder extends IRecognitionService.Stub {
+ private final WeakReference<RecognitionService> mServiceRef;
public RecognitionServiceBinder(RecognitionService service) {
- mInternalService = service;
+ mServiceRef = new WeakReference<RecognitionService>(service);
}
+ @Override
public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
- if (mInternalService != null && mInternalService.checkPermissions(listener)) {
- mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
- MSG_START_LISTENING, mInternalService.new StartListeningArgs(
+ final RecognitionService service = mServiceRef.get();
+ if (service != null && service.checkPermissions(listener)) {
+ service.mHandler.sendMessage(Message.obtain(service.mHandler,
+ MSG_START_LISTENING, service.new StartListeningArgs(
recognizerIntent, listener)));
}
}
+ @Override
public void stopListening(IRecognitionListener listener) {
if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
- if (mInternalService != null && mInternalService.checkPermissions(listener)) {
- mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
+ final RecognitionService service = mServiceRef.get();
+ if (service != null && service.checkPermissions(listener)) {
+ service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_STOP_LISTENING, listener));
}
}
+ @Override
public void cancel(IRecognitionListener listener) {
if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
- if (mInternalService != null && mInternalService.checkPermissions(listener)) {
- mInternalService.mHandler.sendMessage(Message.obtain(mInternalService.mHandler,
+ final RecognitionService service = mServiceRef.get();
+ if (service != null && service.checkPermissions(listener)) {
+ service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_CANCEL, listener));
}
}
public void clearReference() {
- mInternalService = null;
+ mServiceRef.clear();
}
}
}
diff --git a/core/java/android/text/method/KeyListener.java b/core/java/android/text/method/KeyListener.java
index bb79ecd..ce7054c 100644
--- a/core/java/android/text/method/KeyListener.java
+++ b/core/java/android/text/method/KeyListener.java
@@ -57,7 +57,7 @@
/**
* If the key listener wants to handle this key, return true,
- * otherwise return false and the caller (i.e. the widget host)
+ * otherwise return false and the caller (i.e. the widget host)
* will handle the key.
*/
public boolean onKeyDown(View view, Editable text,
@@ -65,7 +65,7 @@
/**
* If the key listener wants to handle this key release, return true,
- * otherwise return false and the caller (i.e. the widget host)
+ * otherwise return false and the caller (i.e. the widget host)
* will handle the key.
*/
public boolean onKeyUp(View view, Editable text,
@@ -73,7 +73,7 @@
/**
* If the key listener wants to other kinds of key events, return true,
- * otherwise return false and the caller (i.e. the widget host)
+ * otherwise return false and the caller (i.e. the widget host)
* will handle the key.
*/
public boolean onKeyOther(View view, Editable text, KeyEvent event);
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index 1b8d57c..3fd28a6 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -228,7 +228,8 @@
}
// Next handle the normal matrix transform:
- ObjectAnimator transformAnimator = createTransformAnimator(startValues, endValues);
+ ObjectAnimator transformAnimator = createTransformAnimator(startValues, endValues,
+ handleParentChange);
if (handleParentChange && transformAnimator != null && mUseOverlay) {
createGhostView(sceneRoot, startValues, endValues);
@@ -238,7 +239,7 @@
}
private ObjectAnimator createTransformAnimator(TransitionValues startValues,
- TransitionValues endValues) {
+ TransitionValues endValues, final boolean handleParentChange) {
Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
@@ -277,7 +278,12 @@
@Override
public void onAnimationEnd(Animator animation) {
if (!mIsCanceled) {
- setCurrentMatrix(finalEndMatrix);
+ if (handleParentChange && mUseOverlay) {
+ setCurrentMatrix(finalEndMatrix);
+ } else {
+ view.setTagInternal(R.id.transitionTransform, null);
+ view.setTagInternal(R.id.parentMatrix, null);
+ }
}
ANIMATION_MATRIX_PROPERTY.set(view, null);
transforms.restore(view);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b454681..1ecc8d9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5033,7 +5033,7 @@
* <strong>Note:</strong> When a View clears focus the framework is trying
* to give focus to the first focusable View from the top. Hence, if this
* View is the first from the top that can take focus, then all callbacks
- * related to clearing focus will be invoked after wich the framework will
+ * related to clearing focus will be invoked after which the framework will
* give focus to this view.
* </p>
*/
@@ -6379,7 +6379,7 @@
* @see #setFitsSystemWindows(boolean)
* @see #setSystemUiVisibility(int)
*
- * @deprecated As of API XX use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
+ * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
* insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
* {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
* to implement handling their own insets.
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index c51d8a7..ff992d3 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -75,7 +75,7 @@
* behavior you should adopt for a particular call, please mimic the
* default TextView implementation in the latest Android version, and
* if you decide to drift from it, please consider carefully that
- * inconsistencies in text edition behavior is almost universally felt
+ * inconsistencies in text editor behavior is almost universally felt
* as a bad thing by users.</p>
*
* <h3>Cursors, selections and compositions</h3>
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 23f911c..5b604cd 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1403,7 +1403,7 @@
* {@link android.widget.RelativeLayout RelativeLayout}, such as
* ALIGN_WITH_PARENT_LEFT.
* @param anchor The id of another view to use as an anchor,
- * or a boolean value(represented as {@link RelativeLayout#TRUE})
+ * or a boolean value (represented as {@link RelativeLayout#TRUE}
* for true or 0 for false). For verbs that don't refer to another sibling
* (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1.
* @see #addRule(int)
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a80d70a..5cdee53 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7378,8 +7378,8 @@
* to turn off ellipsizing.
*
* If {@link #setMaxLines} has been used to set two or more lines,
- * {@link android.text.TextUtils.TruncateAt#END} and
- * {@link android.text.TextUtils.TruncateAt#MARQUEE}* are only supported
+ * only {@link android.text.TextUtils.TruncateAt#END} and
+ * {@link android.text.TextUtils.TruncateAt#MARQUEE} are supported
* (other ellipsizing types will not do anything).
*
* @attr ref android.R.styleable#TextView_ellipsize
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png b/core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png
deleted file mode 100644
index 1b41de4..0000000
--- a/core/res/res/drawable-hdpi/ic_audio_alarm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png b/core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png
deleted file mode 100644
index 45ed7b6..0000000
--- a/core/res/res/drawable-hdpi/ic_audio_alarm_mute_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png
deleted file mode 100644
index a89f45f..0000000
--- a/core/res/res/drawable-hdpi/ic_audio_ring_notif_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png
deleted file mode 100644
index d03bade..0000000
--- a/core/res/res/drawable-hdpi/ic_audio_ring_notif_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png b/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png
deleted file mode 100644
index 4199106..0000000
--- a/core/res/res/drawable-hdpi/ic_audio_ring_notif_vibrate_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png b/core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png
deleted file mode 100644
index 6ea2693..0000000
--- a/core/res/res/drawable-hdpi/ic_audio_vol_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png b/core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png
deleted file mode 100644
index 4256385..0000000
--- a/core/res/res/drawable-hdpi/ic_audio_vol_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png b/core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png
deleted file mode 100644
index fab95aa..0000000
--- a/core/res/res/drawable-mdpi/ic_audio_alarm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png b/core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png
deleted file mode 100644
index 451e932..0000000
--- a/core/res/res/drawable-mdpi/ic_audio_alarm_mute_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png
deleted file mode 100644
index 1ce4f52..0000000
--- a/core/res/res/drawable-mdpi/ic_audio_ring_notif_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png
deleted file mode 100644
index cb17415..0000000
--- a/core/res/res/drawable-mdpi/ic_audio_ring_notif_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png b/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png
deleted file mode 100644
index 2d99b76..0000000
--- a/core/res/res/drawable-mdpi/ic_audio_ring_notif_vibrate_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png b/core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png
deleted file mode 100644
index c32fdbc0d..0000000
--- a/core/res/res/drawable-mdpi/ic_audio_vol_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png b/core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png
deleted file mode 100644
index 0dfc21f..0000000
--- a/core/res/res/drawable-mdpi/ic_audio_vol_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png
deleted file mode 100644
index c1f56a1..0000000
--- a/core/res/res/drawable-xhdpi/ic_audio_alarm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png
deleted file mode 100644
index 0d7034f..0000000
--- a/core/res/res/drawable-xhdpi/ic_audio_alarm_mute_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png
deleted file mode 100644
index 0df1934..0000000
--- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png
deleted file mode 100644
index 85acb93..0000000
--- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
deleted file mode 100644
index 122c708..0000000
--- a/core/res/res/drawable-xhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png
deleted file mode 100644
index 4e2e20e..0000000
--- a/core/res/res/drawable-xhdpi/ic_audio_vol_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png b/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png
deleted file mode 100644
index 64a5215..0000000
--- a/core/res/res/drawable-xhdpi/ic_audio_vol_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png
deleted file mode 100755
index c1c3d35..0000000
--- a/core/res/res/drawable-xxhdpi/ic_audio_alarm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png
deleted file mode 100644
index 4bcee68..0000000
--- a/core/res/res/drawable-xxhdpi/ic_audio_alarm_mute_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png
deleted file mode 100644
index 699711c..0000000
--- a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png
deleted file mode 100644
index 19d92ba..0000000
--- a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
deleted file mode 100644
index fdcfd56..0000000
--- a/core/res/res/drawable-xxhdpi/ic_audio_ring_notif_vibrate_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png
deleted file mode 100755
index 15b6311..0000000
--- a/core/res/res/drawable-xxhdpi/ic_audio_vol_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png
deleted file mode 100644
index b8f4111..0000000
--- a/core/res/res/drawable-xxhdpi/ic_audio_vol_mute_am_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/ic_audio_alarm.xml b/core/res/res/drawable/ic_audio_alarm.xml
index d3e5470..fc4bf10 100644
--- a/core/res/res/drawable/ic_audio_alarm.xml
+++ b/core/res/res/drawable/ic_audio_alarm.xml
@@ -1,19 +1,24 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+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
+ 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
+ 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.
+ 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.
-->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_alarm_alpha"
- android:tint="?attr/colorControlNormal" />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="?android:attr/colorControlNormal"
+ android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_audio_alarm_mute.xml b/core/res/res/drawable/ic_audio_alarm_mute.xml
index 7d85872..1d24081 100644
--- a/core/res/res/drawable/ic_audio_alarm_mute.xml
+++ b/core/res/res/drawable/ic_audio_alarm_mute.xml
@@ -1,19 +1,24 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+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
+ 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
+ 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.
+ 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.
-->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_alarm_mute_alpha"
- android:tint="?attr/colorControlNormal" />
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="?android:attr/colorControlNormal"
+ android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_audio_vol.xml b/core/res/res/drawable/ic_audio_vol.xml
index 8d07ded..a55be93 100644
--- a/core/res/res/drawable/ic_audio_vol.xml
+++ b/core/res/res/drawable/ic_audio_vol.xml
@@ -1,23 +1,24 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
-/*
- * Copyright 2013, 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.
- */
--->
+Copyright (C) 2014 The Android Open Source Project
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_vol_am_alpha"
- android:autoMirrored="true"
- android:tint="?attr/colorControlNormal" />
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="?android:attr/colorControlNormal"
+ android:pathData="M6.0,18.0l0.0,12.0l8.0,0.0l10.0,10.0L24.0,8.0L14.0,18.0L6.0,18.0zm27.0,6.0c0.0,-3.53 -2.04,-6.58 -5.0,-8.05l0.0,16.11c2.96,-1.48 5.0,-4.53 5.0,-8.06zM28.0,6.46l0.0,4.13c5.78,1.72 10.0,7.07 10.0,13.41s-4.22,11.69 -10.0,13.41l0.0,4.13c8.01,-1.82 14.0,-8.97 14.0,-17.54S36.01,8.28 28.0,6.46z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_audio_vol_mute.xml b/core/res/res/drawable/ic_audio_vol_mute.xml
index edbdb23..ab50a7d 100644
--- a/core/res/res/drawable/ic_audio_vol_mute.xml
+++ b/core/res/res/drawable/ic_audio_vol_mute.xml
@@ -1,23 +1,24 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
-/*
- * Copyright 2013, 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.
- */
--->
+Copyright (C) 2014 The Android Open Source Project
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_audio_vol_mute_am_alpha"
- android:autoMirrored="true"
- android:tint="?attr/colorControlNormal" />
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="?android:attr/colorControlNormal"
+ android:pathData="M33.0,24.0c0.0,-3.53 -2.04,-6.58 -5.0,-8.05l0.0,4.42l4.91,4.91c0.06,-0.42 0.09,-0.85 0.09,-1.28zm5.0,0.0c0.0,1.88 -0.41,3.65 -1.08,5.28l3.03,3.03C41.25,29.82 42.0,27.0 42.0,24.0c0.0,-8.56 -5.99,-15.72 -14.0,-17.54l0.0,4.13c5.78,1.72 10.0,7.07 10.0,13.41zM8.55,6.0L6.0,8.55 15.45,18.0L6.0,18.0l0.0,12.0l8.0,0.0l10.0,10.0L24.0,26.55l8.51,8.51c-1.34,1.03 -2.85,1.86 -4.51,2.36l0.0,4.13c2.75,-0.63 5.26,-1.89 7.37,-3.62L39.45,42.0 42.0,39.45l-18.0,-18.0L8.55,6.0zM24.0,8.0l-4.18,4.18L24.0,16.36L24.0,8.0z"/>
+</vector>
diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd
index dee28fe..06bd2d0 100644
--- a/docs/html/guide/topics/resources/drawable-resource.jd
+++ b/docs/html/guide/topics/resources/drawable-resource.jd
@@ -67,7 +67,7 @@
<h2 id="Bitmap">Bitmap</h2>
-<p>A bitmap image. Android supports bitmap files in a three formats:
+<p>A bitmap image. Android supports bitmap files in three formats:
{@code .png} (preferred), {@code .jpg} (acceptable), {@code .gif} (discouraged).</p>
<p>You can reference a bitmap file directly, using the filename as the resource ID, or create an
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index 304b53d..ec0e2f8 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -112,7 +112,7 @@
your JDK folder, for example <code>C:\Program Files\Java\jdk1.7.0_21</code>.</p>
</p>
</li>
-
+
</ol>
@@ -260,10 +260,10 @@
<h5 id="Troubleshooting" style="margin-bottom:15px"><a href='' class="expandable"
- onclick="toggleExpandable(this,'#ubuntu-trouble');return false;"
+ onclick="toggleExpandable(this,'#UbuntuTrouble');return false;"
>Troubleshooting Ubuntu</a></h5>
-<div id="ubuntu-trouble" style="display:none">
+<div id="UbuntuTrouble" style="display:none">
<ul>
<li>If you need help installing and configuring Java on your
development machine, you might find these resources helpful:
@@ -416,6 +416,9 @@
}
}
-
-
+/* direct link to ubuntu troubleshooting */
+if ( document.location.href.indexOf('#UbuntuTrouble') > -1 ) {
+ $(".linux.docs").show();
+ toggleExpandable(this,'#UbuntuTrouble');
+}
</script>
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 5a433d4..c8200aa 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
page.title=Installing the Eclipse Plugin
-adt.zip.version=23.0.3
-adt.zip.download=ADT-23.0.3.zip
-adt.zip.bytes=103321934
-adt.zip.checksum=ab2f5e2fbbdddeeb7dfd02cd4046538a
+adt.zip.version=23.0.4
+adt.zip.download=ADT-23.0.4.zip
+adt.zip.bytes=103336810
+adt.zip.checksum=91a43dcf686ab73dec2c08b77243492b
@jd:body
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index cf33200..469d11f 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -53,9 +53,44 @@
<p>For a summary of all known issues in ADT, see <a
href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
+
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>ADT 23.0.4</a> <em>(October 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+<dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Java 7 or higher is required if you are targeting the L Developer Preview.</li>
+ <li>Java 1.6 or higher is required if you are targeting other releases.</li>
+ <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+ <li>This version of ADT is designed for use with
+ <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r23.0.4</a>.
+ If you haven't already installed SDK Tools r23.0.4 into your SDK, use the
+ Android SDK Manager to do so.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed duplicate devices in AVD for Wear and TV.</li>
+ </ul>
+ </dd>
+</dl>
+</div>
+</div>
+
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>ADT 23.0.3</a> <em>(August 2014)</em>
</p>
diff --git a/docs/html/training/basics/fragments/fragment-ui.jd b/docs/html/training/basics/fragments/fragment-ui.jd
index 14469bf..4fa5b70 100644
--- a/docs/html/training/basics/fragments/fragment-ui.jd
+++ b/docs/html/training/basics/fragments/fragment-ui.jd
@@ -66,9 +66,9 @@
initial fragment(s) to the activity during the activity's
{@link android.app.Activity#onCreate onCreate()} method.</p>
-<p>An important rule when dealing with fragments—especially those that you add at
-runtime—is that the fragment must have a container {@link android.view.View} in the layout in
-which the fragment's layout will reside.</p>
+<p>An important rule when dealing with fragments—especially when adding fragments at
+runtime—is that your activity layout must include a container {@link android.view.View}
+in which you can insert the fragment.</p>
<p>The following layout is an alternative to the layout shown in the <a
href="creating.html">previous lesson</a> that shows only one fragment at a time. In order to replace
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index 4c8b4f1..9fb3fb4 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -257,7 +257,7 @@
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final TypedArray a = r.obtainAttributes(attrs, R.styleable.AnimatedRotateDrawable);
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible);
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index d78138bc..cb09bbf 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -357,7 +357,8 @@
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
- final TypedArray a = r.obtainAttributes(attrs, R.styleable.AnimatedStateListDrawable);
+ final TypedArray a = obtainAttributes(
+ r, theme, attrs, R.styleable.AnimatedStateListDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible);
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index d87e8e4..9a9fd82 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -272,7 +272,7 @@
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- TypedArray a = r.obtainAttributes(attrs,
+ TypedArray a = obtainAttributes(r, theme, attrs,
com.android.internal.R.styleable.AnimationDrawable);
super.inflateWithAttributes(r, parser, a,
@@ -300,7 +300,8 @@
continue;
}
- a = r.obtainAttributes(attrs, com.android.internal.R.styleable.AnimationDrawableItem);
+ a = obtainAttributes(
+ r, theme, attrs, com.android.internal.R.styleable.AnimationDrawableItem);
int duration = a.getInt(
com.android.internal.R.styleable.AnimationDrawableItem_duration, -1);
if (duration < 0) {
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 61ef81b..40711cf 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -81,7 +81,8 @@
int type;
- TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.ClipDrawable);
+ TypedArray a = obtainAttributes(
+ r, theme, attrs, com.android.internal.R.styleable.ClipDrawable);
int orientation = a.getInt(
com.android.internal.R.styleable.ClipDrawable_clipOrientation,
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 384226f..961d1607 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -84,7 +84,7 @@
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final TypedArray a = r.obtainAttributes(attrs, R.styleable.InsetDrawable);
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
mInsetState.mDrawable = null;
diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java
index 7271b0e..bc1c61d 100644
--- a/graphics/java/android/graphics/drawable/LevelListDrawable.java
+++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java
@@ -105,7 +105,7 @@
continue;
}
- TypedArray a = r.obtainAttributes(attrs,
+ TypedArray a = obtainAttributes(r, theme, attrs,
com.android.internal.R.styleable.LevelListDrawableItem);
low = a.getInt(
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 70482a6..55c9637 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -399,7 +399,7 @@
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final TypedArray a = r.obtainAttributes(attrs,
+ final TypedArray a = obtainAttributes(r, theme, attrs,
com.android.internal.R.styleable.RotateDrawable);
super.inflateWithAttributes(r, parser, a,
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index b40038a..b990249 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -93,7 +93,8 @@
int type;
- TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.ScaleDrawable);
+ TypedArray a = obtainAttributes(
+ r, theme, attrs, com.android.internal.R.styleable.ScaleDrawable);
float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth);
float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight);
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 4c513e9..2eb8a80 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -118,7 +118,7 @@
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final TypedArray a = r.obtainAttributes(attrs, R.styleable.StateListDrawable);
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.StateListDrawable);
super.inflateWithAttributes(r, parser, a,
R.styleable.StateListDrawable_visible);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 8084eda..3453a67 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -694,12 +694,11 @@
if (Settings.CALL_METHOD_GET_SYSTEM.equals(method)) {
if (LOCAL_LOGV) Slog.v(TAG, "call(system:" + request + ") for " + callingUser);
// Check if this request should be (re)directed to the primary user's db
- if (callingUser == UserHandle.USER_OWNER
- || shouldShadowParentProfile(callingUser, sSystemCloneToManagedKeys, request)) {
- dbHelper = getOrEstablishDatabase(UserHandle.USER_OWNER);
- } else {
- dbHelper = getOrEstablishDatabase(callingUser);
+ if (callingUser != UserHandle.USER_OWNER
+ && shouldShadowParentProfile(callingUser, sSystemCloneToManagedKeys, request)) {
+ callingUser = UserHandle.USER_OWNER;
}
+ dbHelper = getOrEstablishDatabase(callingUser);
cache = sSystemCaches.get(callingUser);
return lookupValue(dbHelper, TABLE_SYSTEM, cache, request);
}
@@ -713,10 +712,9 @@
UserManager.DISALLOW_SHARE_LOCATION, new UserHandle(callingUser))) {
return sSecureCaches.get(callingUser).putIfAbsent(request, "");
}
- dbHelper = getOrEstablishDatabase(UserHandle.USER_OWNER);
- } else {
- dbHelper = getOrEstablishDatabase(callingUser);
+ callingUser = UserHandle.USER_OWNER;
}
+ dbHelper = getOrEstablishDatabase(callingUser);
cache = sSecureCaches.get(callingUser);
return lookupValue(dbHelper, TABLE_SECURE, cache, request);
}
diff --git a/packages/SystemUI/res/drawable/ic_audio_alarm.xml b/packages/SystemUI/res/drawable/ic_audio_alarm.xml
new file mode 100644
index 0000000..5dd158e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_audio_alarm.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#ffffffff"
+ android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_audio_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_audio_alarm_mute.xml
new file mode 100644
index 0000000..af445e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_audio_alarm_mute.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#ffffffff"
+ android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_audio_vol.xml b/packages/SystemUI/res/drawable/ic_audio_vol.xml
new file mode 100644
index 0000000..76c14b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_audio_vol.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#ffffffff"
+ android:pathData="M6.0,18.0l0.0,12.0l8.0,0.0l10.0,10.0L24.0,8.0L14.0,18.0L6.0,18.0zm27.0,6.0c0.0,-3.53 -2.04,-6.58 -5.0,-8.05l0.0,16.11c2.96,-1.48 5.0,-4.53 5.0,-8.06zM28.0,6.46l0.0,4.13c5.78,1.72 10.0,7.07 10.0,13.41s-4.22,11.69 -10.0,13.41l0.0,4.13c8.01,-1.82 14.0,-8.97 14.0,-17.54S36.01,8.28 28.0,6.46z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_audio_vol_mute.xml b/packages/SystemUI/res/drawable/ic_audio_vol_mute.xml
new file mode 100644
index 0000000..e158f7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_audio_vol_mute.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="32.0dp"
+ android:height="32.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#ffffffff"
+ android:pathData="M33.0,24.0c0.0,-3.53 -2.04,-6.58 -5.0,-8.05l0.0,4.42l4.91,4.91c0.06,-0.42 0.09,-0.85 0.09,-1.28zm5.0,0.0c0.0,1.88 -0.41,3.65 -1.08,5.28l3.03,3.03C41.25,29.82 42.0,27.0 42.0,24.0c0.0,-8.56 -5.99,-15.72 -14.0,-17.54l0.0,4.13c5.78,1.72 10.0,7.07 10.0,13.41zM8.55,6.0L6.0,8.55 15.45,18.0L6.0,18.0l0.0,12.0l8.0,0.0l10.0,10.0L24.0,26.55l8.51,8.51c-1.34,1.03 -2.85,1.86 -4.51,2.36l0.0,4.13c2.75,-0.63 5.26,-1.89 7.37,-3.62L39.45,42.0 42.0,39.45l-18.0,-18.0L8.55,6.0zM24.0,8.0l-4.18,4.18L24.0,16.36L24.0,8.0z"/>
+</vector>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 40bdea2..360dee5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -127,6 +127,9 @@
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
+ private static final int IC_AUDIO_VOL = com.android.systemui.R.drawable.ic_audio_vol;
+ private static final int IC_AUDIO_VOL_MUTE = com.android.systemui.R.drawable.ic_audio_vol_mute;
+
private final String mTag;
protected final Context mContext;
private final AudioManager mAudioManager;
@@ -182,13 +185,13 @@
false),
AlarmStream(AudioManager.STREAM_ALARM,
R.string.volume_alarm,
- R.drawable.ic_audio_alarm,
- R.drawable.ic_audio_alarm_mute,
+ com.android.systemui.R.drawable.ic_audio_alarm,
+ com.android.systemui.R.drawable.ic_audio_alarm_mute,
false),
MediaStream(AudioManager.STREAM_MUSIC,
R.string.volume_icon_description_media,
- R.drawable.ic_audio_vol,
- R.drawable.ic_audio_vol_mute,
+ IC_AUDIO_VOL,
+ IC_AUDIO_VOL_MUTE,
true),
NotificationStream(AudioManager.STREAM_NOTIFICATION,
R.string.volume_icon_description_notification,
@@ -198,8 +201,8 @@
// for now, use media resources for master volume
MasterStream(STREAM_MASTER,
R.string.volume_icon_description_media, //FIXME should have its own description
- R.drawable.ic_audio_vol,
- R.drawable.ic_audio_vol_mute,
+ IC_AUDIO_VOL,
+ IC_AUDIO_VOL_MUTE,
false),
RemoteStream(STREAM_REMOTE_MUSIC,
R.string.volume_icon_description_media, //FIXME should have its own description
@@ -994,7 +997,7 @@
AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
setMusicIcon(R.drawable.ic_audio_bt, R.drawable.ic_audio_bt_mute);
} else {
- setMusicIcon(R.drawable.ic_audio_vol, R.drawable.ic_audio_vol_mute);
+ setMusicIcon(IC_AUDIO_VOL, IC_AUDIO_VOL_MUTE);
}
break;
}
diff --git a/preloaded-classes b/preloaded-classes
index 649255f..7686431 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -804,9 +804,6 @@
android.hardware.input.InputDeviceIdentifier$1
android.hardware.input.InputManager
android.hardware.input.InputManager$InputDevicesChangedListener
-android.hardware.location.ActivityRecognitionHardware
-android.hardware.location.IActivityRecognitionHardware
-android.hardware.location.IActivityRecognitionHardware$Stub
android.hardware.soundtrigger.SoundTrigger
android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel
android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel$1
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 85ab249..3dab17f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -90,6 +90,7 @@
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
+import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
@@ -137,6 +138,7 @@
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.PacManager;
+import com.android.server.connectivity.PermissionMonitor;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
@@ -170,6 +172,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -225,6 +228,8 @@
private Tethering mTethering;
+ private final PermissionMonitor mPermissionMonitor;
+
private KeyStore mKeyStore;
@GuardedBy("mVpns")
@@ -400,7 +405,7 @@
private ArrayList mInetLog;
// track the current default http proxy - tell the world if we get a new one (real change)
- private ProxyInfo mDefaultProxy = null;
+ private volatile ProxyInfo mDefaultProxy = null;
private Object mProxyLock = new Object();
private boolean mDefaultProxyDisabled = false;
@@ -702,6 +707,8 @@
mTethering = new Tethering(mContext, mNetd, statsService, mHandler.getLooper());
+ mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
+
//set up the listener for user state for creating user VPNs
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_STARTING);
@@ -1484,6 +1491,8 @@
}
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
+
+ mPermissionMonitor.startMonitoring();
}
private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
@@ -1785,6 +1794,10 @@
return false;
}
+ private boolean isRequest(NetworkRequest request) {
+ return mNetworkRequests.get(request).isRequest;
+ }
+
// must be stateless - things change under us.
private class NetworkStateTrackerHandler extends Handler {
public NetworkStateTrackerHandler(Looper looper) {
@@ -1888,6 +1901,9 @@
loge("EVENT_SET_EXPLICITLY_SELECTED from unknown NetworkAgent");
break;
}
+ if (nai.created && !nai.networkMisc.explicitlySelected) {
+ loge("ERROR: created network explicitly selected.");
+ }
nai.networkMisc.explicitlySelected = true;
break;
}
@@ -1897,8 +1913,14 @@
boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
if (valid) {
if (DBG) log("Validated " + nai.name());
+ final boolean previouslyValidated = nai.validated;
+ final int previousScore = nai.getCurrentScore();
nai.validated = true;
- rematchNetworkAndRequests(nai);
+ rematchNetworkAndRequests(nai, !previouslyValidated);
+ // If score has changed, rebroadcast to NetworkFactories. b/17726566
+ if (nai.getCurrentScore() != previousScore) {
+ sendUpdatedScoreToFactories(nai);
+ }
}
updateInetCondition(nai, valid);
// Let the NetworkAgent know the state of its network
@@ -2071,6 +2093,7 @@
}
// Since we've lost the network, go through all the requests that
// it was satisfying and see if any other factory can satisfy them.
+ // TODO: This logic may be better replaced with a call to rematchAllNetworksAndRequests
final ArrayList<NetworkAgentInfo> toActivate = new ArrayList<NetworkAgentInfo>();
for (int i = 0; i < nai.networkRequests.size(); i++) {
NetworkRequest request = nai.networkRequests.valueAt(i);
@@ -2106,7 +2129,9 @@
requestNetworkTransitionWakelock(nai.name());
}
for (NetworkAgentInfo networkToActivate : toActivate) {
+ networkToActivate.networkLingered.clear();
networkToActivate.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
+ rematchNetworkAndRequests(networkToActivate, false);
}
}
}
@@ -2144,6 +2169,7 @@
bestNetwork.networkLingered.clear();
bestNetwork.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
}
+ // TODO: This logic may be better replaced with a call to rematchNetworkAndRequests
bestNetwork.addRequest(nri.request);
mNetworkForRequestId.put(nri.request.requestId, bestNetwork);
notifyNetworkCallback(bestNetwork, nri);
@@ -2188,7 +2214,7 @@
boolean keep = nai.isVPN();
for (int i = 0; i < nai.networkRequests.size() && !keep; i++) {
NetworkRequest r = nai.networkRequests.valueAt(i);
- if (mNetworkRequests.get(r).isRequest) keep = true;
+ if (isRequest(r)) keep = true;
}
if (!keep) {
if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
@@ -2472,6 +2498,10 @@
if (nai == null) return;
if (DBG) log("reportBadNetwork(" + nai.name() + ") by " + uid);
synchronized (nai) {
+ // Validating an uncreated network could result in a call to rematchNetworkAndRequests()
+ // which isn't meant to work on uncreated networks.
+ if (!nai.created) return;
+
if (isNetworkBlocked(nai, uid)) return;
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
@@ -2530,12 +2560,12 @@
} finally {
Binder.restoreCallingIdentity(token);
}
- }
- if (mGlobalProxy == null) {
- proxyProperties = mDefaultProxy;
+ if (mGlobalProxy == null) {
+ proxyProperties = mDefaultProxy;
+ }
+ sendProxyBroadcast(proxyProperties);
}
- sendProxyBroadcast(proxyProperties);
}
private void loadGlobalProxy() {
@@ -3533,6 +3563,10 @@
updateDnses(newLp, oldLp, netId, flushDns);
updateClat(newLp, oldLp, networkAgent);
if (isDefaultNetwork(networkAgent)) handleApplyDefaultProxy(newLp.getHttpProxy());
+ // TODO - move this check to cover the whole function
+ if (!Objects.equals(newLp, oldLp)) {
+ notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
+ }
}
private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo na) {
@@ -3670,10 +3704,22 @@
private void updateCapabilities(NetworkAgentInfo networkAgent,
NetworkCapabilities networkCapabilities) {
- // TODO - what else here? Verify still satisfies everybody?
- // Check if satisfies somebody new? call callbacks?
- synchronized (networkAgent) {
- networkAgent.networkCapabilities = networkCapabilities;
+ // TODO - turn this on in MR1 when we have more dogfooding time.
+ // rematchAllNetworksAndRequests();
+ if (!Objects.equals(networkAgent.networkCapabilities, networkCapabilities)) {
+ synchronized (networkAgent) {
+ networkAgent.networkCapabilities = networkCapabilities;
+ }
+ notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_CAP_CHANGED);
+ }
+ }
+
+ private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
+ for (int i = 0; i < nai.networkRequests.size(); i++) {
+ NetworkRequest nr = nai.networkRequests.valueAt(i);
+ // Don't send listening requests to factories. b/17393458
+ if (!isRequest(nr)) continue;
+ sendUpdatedScoreToFactories(nr, nai.getCurrentScore());
}
}
@@ -3688,37 +3734,32 @@
private void callCallbackForRequest(NetworkRequestInfo nri,
NetworkAgentInfo networkAgent, int notificationType) {
if (nri.messenger == null) return; // Default request has no msgr
- Object o;
- int a1 = 0;
- int a2 = 0;
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(NetworkRequest.class.getSimpleName(),
+ new NetworkRequest(nri.request));
+ Message msg = Message.obtain();
+ if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL &&
+ notificationType != ConnectivityManager.CALLBACK_RELEASED) {
+ bundle.putParcelable(Network.class.getSimpleName(), networkAgent.network);
+ }
switch (notificationType) {
- case ConnectivityManager.CALLBACK_LOSING:
- a1 = 30 * 1000; // TODO - read this from NetworkMonitor
- // fall through
- case ConnectivityManager.CALLBACK_PRECHECK:
- case ConnectivityManager.CALLBACK_AVAILABLE:
- case ConnectivityManager.CALLBACK_LOST:
- case ConnectivityManager.CALLBACK_CAP_CHANGED:
+ case ConnectivityManager.CALLBACK_LOSING: {
+ msg.arg1 = 30 * 1000; // TODO - read this from NetworkMonitor
+ break;
+ }
+ case ConnectivityManager.CALLBACK_CAP_CHANGED: {
+ bundle.putParcelable(NetworkCapabilities.class.getSimpleName(),
+ new NetworkCapabilities(networkAgent.networkCapabilities));
+ break;
+ }
case ConnectivityManager.CALLBACK_IP_CHANGED: {
- o = new NetworkRequest(nri.request);
- a2 = networkAgent.network.netId;
+ bundle.putParcelable(LinkProperties.class.getSimpleName(),
+ new LinkProperties(networkAgent.linkProperties));
break;
}
- case ConnectivityManager.CALLBACK_UNAVAIL:
- case ConnectivityManager.CALLBACK_RELEASED: {
- o = new NetworkRequest(nri.request);
- break;
- }
- default: {
- loge("Unknown notificationType " + notificationType);
- return;
- }
}
- Message msg = Message.obtain();
- msg.arg1 = a1;
- msg.arg2 = a2;
- msg.obj = o;
msg.what = notificationType;
+ msg.setData(bundle);
try {
if (VDBG) {
log("sending notification " + notifyTypeToName(notificationType) +
@@ -3731,22 +3772,24 @@
}
}
+ private void teardownUnneededNetwork(NetworkAgentInfo nai) {
+ for (int i = 0; i < nai.networkRequests.size(); i++) {
+ NetworkRequest nr = nai.networkRequests.valueAt(i);
+ // Ignore listening requests.
+ if (!isRequest(nr)) continue;
+ loge("Dead network still had at least " + nr);
+ break;
+ }
+ nai.asyncChannel.disconnect();
+ }
+
private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
if (oldNetwork == null) {
loge("Unknown NetworkAgentInfo in handleLingerComplete");
return;
}
- if (DBG) {
- log("handleLingerComplete for " + oldNetwork.name());
- for (int i = 0; i < oldNetwork.networkRequests.size(); i++) {
- NetworkRequest nr = oldNetwork.networkRequests.valueAt(i);
- // Ignore listening requests.
- if (mNetworkRequests.get(nr).isRequest == false) continue;
- loge("Dead network still had at least " + nr);
- break;
- }
- }
- oldNetwork.asyncChannel.disconnect();
+ if (DBG) log("handleLingerComplete for " + oldNetwork.name());
+ teardownUnneededNetwork(oldNetwork);
}
private void makeDefault(NetworkAgentInfo newNetwork) {
@@ -3768,21 +3811,32 @@
// satisfied by newNetwork, and reassigns to newNetwork
// any such requests for which newNetwork is the best.
//
- // - Tears down any Networks that as a result are no longer
+ // - Lingers any Networks that as a result are no longer
// needed. A network is needed if it is the best network for
// one or more NetworkRequests, or if it is a VPN.
//
- // - Tears down newNetwork if it is validated but turns out to be
- // unneeded. Does not tear down newNetwork if it is
- // unvalidated, because future validation may improve
- // newNetwork's score enough that it is needed.
+ // - Tears down newNetwork if it just became validated
+ // (i.e. nascent==true) but turns out to be unneeded.
+ // Does not tear down newNetwork if it is unvalidated,
+ // because future validation may improve newNetwork's
+ // score enough that it is needed.
//
// NOTE: This function only adds NetworkRequests that "newNetwork" could satisfy,
// it does not remove NetworkRequests that other Networks could better satisfy.
// If you need to handle decreases in score, use {@link rematchAllNetworksAndRequests}.
// This function should be used when possible instead of {@code rematchAllNetworksAndRequests}
// as it performs better by a factor of the number of Networks.
- private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork) {
+ //
+ // @param nascent indicates if newNetwork just became validated, in which case it should be
+ // torn down if unneeded. If nascent is false, no action is taken if newNetwork
+ // is found to be unneeded by this call. Presumably, in this case, either:
+ // - newNetwork is unvalidated (and left alive), or
+ // - the NetworkRequests keeping newNetwork alive have been transitioned to
+ // another higher scoring network by another call to rematchNetworkAndRequests()
+ // and this other call also lingered newNetwork.
+ private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, boolean nascent) {
+ if (!newNetwork.created) loge("ERROR: uncreated network being rematched.");
+ if (nascent && !newNetwork.validated) loge("ERROR: nascent network not validated.");
boolean keep = newNetwork.isVPN();
boolean isNewDefault = false;
if (DBG) log("rematching " + newNetwork.name());
@@ -3868,11 +3922,11 @@
}
// Linger any networks that are no longer needed.
for (NetworkAgentInfo nai : affectedNetworks) {
- boolean teardown = !nai.isVPN();
+ boolean teardown = !nai.isVPN() && nai.validated;
for (int i = 0; i < nai.networkRequests.size() && teardown; i++) {
NetworkRequest nr = nai.networkRequests.valueAt(i);
try {
- if (mNetworkRequests.get(nr).isRequest) {
+ if (isRequest(nr)) {
teardown = false;
}
} catch (Exception e) {
@@ -3927,20 +3981,16 @@
}
notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE);
- } else if (newNetwork.validated) {
- // Only tear down validated networks here. Leave unvalidated to either become
+ } else if (nascent) {
+ // Only tear down newly validated networks here. Leave unvalidated to either become
// validated (and get evaluated against peers, one losing here) or
// NetworkMonitor reports a bad network and we tear it down then.
+ // Networks that have been up for a while and are validated should be torn down via
+ // the lingering process so communication on that network is given time to wrap up.
// TODO: Could teardown unvalidated networks when their NetworkCapabilities
// satisfy no NetworkRequests.
- if (DBG && newNetwork.networkRequests.size() != 0) {
- loge("tearing down network with live requests:");
- for (int i=0; i < newNetwork.networkRequests.size(); i++) {
- loge(" " + newNetwork.networkRequests.valueAt(i));
- }
- }
if (DBG) log("Validated network turns out to be unwanted. Tear it down.");
- newNetwork.asyncChannel.disconnect();
+ teardownUnneededNetwork(newNetwork);
}
}
@@ -3962,10 +4012,10 @@
// can only add more NetworkRequests satisfied by "changed", and this is exactly what
// rematchNetworkAndRequests() handles.
if (changed != null && oldScore < changed.getCurrentScore()) {
- rematchNetworkAndRequests(changed);
+ rematchNetworkAndRequests(changed, false);
} else {
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- rematchNetworkAndRequests(nai);
+ rematchNetworkAndRequests(nai, false);
}
}
}
@@ -4039,14 +4089,7 @@
// TODO: support proxy per network.
}
// Consider network even though it is not yet validated.
- // TODO: All the if-statement conditions can be removed now that validation only confers
- // a score increase.
- if (mNetworkForRequestId.get(mDefaultRequest.requestId) == null &&
- networkAgent.isVPN() == false &&
- mDefaultRequest.networkCapabilities.satisfiedByNetworkCapabilities(
- networkAgent.networkCapabilities)) {
- rematchNetworkAndRequests(networkAgent);
- }
+ rematchNetworkAndRequests(networkAgent, false);
} else if (state == NetworkInfo.State.DISCONNECTED ||
state == NetworkInfo.State.SUSPENDED) {
networkAgent.asyncChannel.disconnect();
@@ -4076,12 +4119,7 @@
if (nai.created) rematchAllNetworksAndRequests(nai, oldScore);
- for (int i = 0; i < nai.networkRequests.size(); i++) {
- NetworkRequest nr = nai.networkRequests.valueAt(i);
- // Don't send listening requests to factories. b/17393458
- if (mNetworkRequests.get(nr).isRequest == false) continue;
- sendUpdatedScoreToFactories(nr, score);
- }
+ sendUpdatedScoreToFactories(nai);
}
// notify only this one new request of the current state
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 822007a..020c951 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -16,7 +16,6 @@
package com.android.server;
-import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.SHUTDOWN;
@@ -2059,20 +2058,26 @@
}
@Override
- public void setPermission(boolean internal, boolean changeNetState, int[] uids) {
+ public void setPermission(String permission, int[] uids) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- final Command cmd = new Command("network", "permission", "user", "set");
- if (internal) cmd.appendArg(CONNECTIVITY_INTERNAL);
- if (changeNetState) cmd.appendArg(CHANGE_NETWORK_STATE);
- for (int i=0; i<uids.length; i++) {
- cmd.appendArg(uids[i]);
- }
-
- try {
- mConnector.execute(cmd);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND];
+ argv[0] = "permission";
+ argv[1] = "user";
+ argv[2] = "set";
+ argv[3] = permission;
+ int argc = 4;
+ // Avoid overly long commands by limiting number of UIDs per command.
+ for (int i = 0; i < uids.length; ++i) {
+ argv[argc++] = uids[i];
+ if (i == uids.length - 1 || argc == argv.length) {
+ try {
+ mConnector.execute("network", Arrays.copyOf(argv, argc));
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ argc = 4;
+ }
}
}
@@ -2080,15 +2085,22 @@
public void clearPermission(int[] uids) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- final Command cmd = new Command("network", "permission", "user", "clear");
- for (int i=0; i<uids.length; i++) {
- cmd.appendArg(uids[i]);
- }
-
- try {
- mConnector.execute(cmd);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
+ argv[0] = "permission";
+ argv[1] = "user";
+ argv[2] = "clear";
+ int argc = 3;
+ // Avoid overly long commands by limiting number of UIDs per command.
+ for (int i = 0; i < uids.length; ++i) {
+ argv[argc++] = uids[i];
+ if (i == uids.length - 1 || argc == argv.length) {
+ try {
+ mConnector.execute("network", Arrays.copyOf(argv, argc));
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ argc = 3;
+ }
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 5022b28..0ea66b9 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -166,14 +166,14 @@
// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
private final int[] mOomMinFreeLow = new int[] {
- 8192, 12288, 16384,
- 24576, 28672, 32768
+ 12288, 18432, 24576,
+ 36864, 43008, 49152
};
// These are the high-end OOM level limits. This is appropriate for a
// 1280x800 or larger screen with around 1GB RAM. Values are in KB.
private final int[] mOomMinFreeHigh = new int[] {
- 49152, 61440, 73728,
- 86016, 98304, 122880
+ 73728, 92160, 110592,
+ 129024, 147456, 184320
};
// The actual OOM killer memory levels we are using.
private final int[] mOomMinFree = new int[mOomAdj.length];
@@ -231,7 +231,11 @@
Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
}
- final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;
+ // We've now baked in the increase to the basic oom values above, since
+ // they seem to be useful more generally for devices that are tight on
+ // memory than just for 64 bit. This should probably have some more
+ // tuning done, so not deleting it quite yet...
+ final boolean is64bit = false; //Build.SUPPORTED_64_BIT_ABIS.length > 0;
for (int i=0; i<mOomAdj.length; i++) {
int low = mOomMinFreeLow[i];
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
new file mode 100644
index 0000000..238402f
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+
+package com.android.server.connectivity;
+
+import static android.Manifest.permission.CHANGE_NETWORK_STATE;
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
+import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A utility class to inform Netd of UID permisisons.
+ * Does a mass update at boot and then monitors for app install/remove.
+ *
+ * @hide
+ */
+public class PermissionMonitor {
+ private static final String TAG = "PermissionMonitor";
+ private static final boolean DBG = true;
+ private static final boolean SYSTEM = true;
+ private static final boolean NETWORK = false;
+
+ private final Context mContext;
+ private final PackageManager mPackageManager;
+ private final UserManager mUserManager;
+ private final INetworkManagementService mNetd;
+ private final BroadcastReceiver mIntentReceiver;
+
+ // Values are User IDs.
+ private final Set<Integer> mUsers = new HashSet<Integer>();
+
+ // Keys are App IDs. Values are true for SYSTEM permission and false for NETWORK permission.
+ private final Map<Integer, Boolean> mApps = new HashMap<Integer, Boolean>();
+
+ public PermissionMonitor(Context context, INetworkManagementService netd) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+ mUserManager = UserManager.get(context);
+ mNetd = netd;
+ mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ int appUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ Uri appData = intent.getData();
+ String appName = appData != null ? appData.getSchemeSpecificPart() : null;
+
+ if (Intent.ACTION_USER_ADDED.equals(action)) {
+ onUserAdded(user);
+ } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ onUserRemoved(user);
+ } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ onAppAdded(appName, appUid);
+ } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ onAppRemoved(appUid);
+ }
+ }
+ };
+ }
+
+ // Intended to be called only once at startup, after the system is ready. Installs a broadcast
+ // receiver to monitor ongoing UID changes, so this shouldn't/needn't be called again.
+ public synchronized void startMonitoring() {
+ log("Monitoring");
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_USER_ADDED);
+ intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+
+ intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ intentFilter.addDataScheme("package");
+ mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, intentFilter, null, null);
+
+ List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS);
+ if (apps == null) {
+ loge("No apps");
+ return;
+ }
+
+ for (PackageInfo app : apps) {
+ int uid = app.applicationInfo != null ? app.applicationInfo.uid : -1;
+ if (uid < 0) {
+ continue;
+ }
+
+ boolean isNetwork = hasNetworkPermission(app);
+ boolean isSystem = hasSystemPermission(app);
+
+ if (isNetwork || isSystem) {
+ Boolean permission = mApps.get(uid);
+ // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
+ // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
+ if (permission == null || permission == NETWORK) {
+ mApps.put(uid, isSystem);
+ }
+ }
+ }
+
+ List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users
+ if (users != null) {
+ for (UserInfo user : users) {
+ mUsers.add(user.id);
+ }
+ }
+
+ log("Users: " + mUsers.size() + ", Apps: " + mApps.size());
+ update(mUsers, mApps, true);
+ }
+
+ private boolean hasPermission(PackageInfo app, String permission) {
+ if (app.requestedPermissions != null) {
+ for (String p : app.requestedPermissions) {
+ if (permission.equals(p)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean hasNetworkPermission(PackageInfo app) {
+ return hasPermission(app, CHANGE_NETWORK_STATE);
+ }
+
+ private boolean hasSystemPermission(PackageInfo app) {
+ int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
+ if ((flags & FLAG_SYSTEM) != 0 || (flags & FLAG_UPDATED_SYSTEM_APP) != 0) {
+ return true;
+ }
+ return hasPermission(app, CONNECTIVITY_INTERNAL);
+ }
+
+ private int[] toIntArray(List<Integer> list) {
+ int[] array = new int[list.size()];
+ for (int i = 0; i < list.size(); i++) {
+ array[i] = list.get(i);
+ }
+ return array;
+ }
+
+ private void update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add) {
+ List<Integer> network = new ArrayList<Integer>();
+ List<Integer> system = new ArrayList<Integer>();
+ for (Entry<Integer, Boolean> app : apps.entrySet()) {
+ List<Integer> list = app.getValue() ? system : network;
+ for (int user : users) {
+ list.add(UserHandle.getUid(user, app.getKey()));
+ }
+ }
+ try {
+ if (add) {
+ mNetd.setPermission(CHANGE_NETWORK_STATE, toIntArray(network));
+ mNetd.setPermission(CONNECTIVITY_INTERNAL, toIntArray(system));
+ } else {
+ mNetd.clearPermission(toIntArray(network));
+ mNetd.clearPermission(toIntArray(system));
+ }
+ } catch (RemoteException e) {
+ loge("Exception when updating permissions: " + e);
+ }
+ }
+
+ private synchronized void onUserAdded(int user) {
+ if (user < 0) {
+ loge("Invalid user in onUserAdded: " + user);
+ return;
+ }
+ mUsers.add(user);
+
+ Set<Integer> users = new HashSet<Integer>();
+ users.add(user);
+ update(users, mApps, true);
+ }
+
+ private synchronized void onUserRemoved(int user) {
+ if (user < 0) {
+ loge("Invalid user in onUserRemoved: " + user);
+ return;
+ }
+ mUsers.remove(user);
+
+ Set<Integer> users = new HashSet<Integer>();
+ users.add(user);
+ update(users, mApps, false);
+ }
+
+ private synchronized void onAppAdded(String appName, int appUid) {
+ if (TextUtils.isEmpty(appName) || appUid < 0) {
+ loge("Invalid app in onAppAdded: " + appName + " | " + appUid);
+ return;
+ }
+
+ try {
+ PackageInfo app = mPackageManager.getPackageInfo(appName, GET_PERMISSIONS);
+ boolean isNetwork = hasNetworkPermission(app);
+ boolean isSystem = hasSystemPermission(app);
+ if (isNetwork || isSystem) {
+ Boolean permission = mApps.get(appUid);
+ // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
+ // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
+ if (permission == null || permission == NETWORK) {
+ mApps.put(appUid, isSystem);
+
+ Map<Integer, Boolean> apps = new HashMap<Integer, Boolean>();
+ apps.put(appUid, isSystem);
+ update(mUsers, apps, true);
+ }
+ }
+ } catch (NameNotFoundException e) {
+ loge("NameNotFoundException in onAppAdded: " + e);
+ }
+ }
+
+ private synchronized void onAppRemoved(int appUid) {
+ if (appUid < 0) {
+ loge("Invalid app in onAppRemoved: " + appUid);
+ return;
+ }
+ mApps.remove(appUid);
+
+ Map<Integer, Boolean> apps = new HashMap<Integer, Boolean>();
+ apps.put(appUid, NETWORK); // doesn't matter which permission we pick here
+ update(mUsers, apps, false);
+ }
+
+ private static void log(String s) {
+ if (DBG) {
+ Log.d(TAG, s);
+ }
+ }
+
+ private static void loge(String s) {
+ Log.e(TAG, s);
+ }
+}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index adc96f7..6dcbc42 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -16,7 +16,6 @@
package com.android.server.content;
-import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
@@ -481,7 +480,7 @@
mContext.registerReceiverAsUser(mAccountsUpdatedReceiver,
UserHandle.ALL,
new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
- Manifest.permission.ACCOUNT_MANAGER, null);
+ null, null);
}
// Pick a random second in a day to seed all periodic syncs
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e3a25c0..2d5b99e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -563,6 +563,12 @@
state = Display.STATE_OFF;
}
+ // Animate the screen state change unless already animating.
+ // The transition may be deferred, so after this point we will use the
+ // actual state instead of the desired one.
+ animateScreenStateChange(state, performScreenOffTransition);
+ state = mPowerState.getScreenState();
+
// Use zero brightness when screen is off.
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF;
@@ -636,13 +642,9 @@
mAppliedLowPower = true;
}
- // Animate the screen state change unless already animating.
- animateScreenStateChange(state, performScreenOffTransition);
-
// Animate the screen brightness when the screen is on or dozing.
// Skip the animation when the screen is off or suspended.
- final int actualState = mPowerState.getScreenState();
- if (actualState == Display.STATE_ON || actualState == Display.STATE_DOZE) {
+ if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
animateScreenBrightness(brightness,
slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
} else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d8e5a98..22f060f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -75,6 +75,7 @@
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
+import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -187,6 +188,7 @@
boolean mSystemReady;
private boolean mDisableNotificationEffects;
+ private int mCallState;
NotificationRecord mSoundNotification;
NotificationRecord mVibrateNotification;
@@ -490,7 +492,7 @@
synchronized (mNotificationList) {
mDisableNotificationEffects =
(status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
- if (disableNotificationEffects()) {
+ if (disableNotificationEffects(null) != null) {
// cancel whatever's going on
long identity = Binder.clearCallingIdentity();
try {
@@ -875,6 +877,7 @@
mZenModeHelper.updateZenMode();
mUserProfiles.updateCache(getContext());
+ listenForCallState();
// register for various Intents
IntentFilter filter = new IntentFilter();
@@ -1510,8 +1513,17 @@
return keys.toArray(new String[keys.size()]);
}
- private boolean disableNotificationEffects() {
- return mDisableNotificationEffects || (mListenerHints & HINT_HOST_DISABLE_EFFECTS) != 0;
+ private String disableNotificationEffects(NotificationRecord record) {
+ if (mDisableNotificationEffects) {
+ return "booleanState";
+ }
+ if ((mListenerHints & HINT_HOST_DISABLE_EFFECTS) != 0) {
+ return "listenerHints";
+ }
+ if (mCallState != TelephonyManager.CALL_STATE_IDLE && !mZenModeHelper.isCall(record)) {
+ return "callState";
+ }
+ return null;
}
void dumpImpl(PrintWriter pw, DumpFilter filter) {
@@ -1563,6 +1575,7 @@
pw.println(" mSoundNotification=" + mSoundNotification);
pw.println(" mVibrateNotification=" + mVibrateNotification);
pw.println(" mDisableNotificationEffects=" + mDisableNotificationEffects);
+ pw.println(" mCallState=" + callStateToString(mCallState));
pw.println(" mSystemReady=" + mSystemReady);
}
pw.println(" mArchive=" + mArchive.toString());
@@ -1839,7 +1852,11 @@
}
// If we're not supposed to beep, vibrate, etc. then don't.
- if (!disableNotificationEffects()
+ final String disableEffects = disableNotificationEffects(record);
+ if (disableEffects != null) {
+ ZenLog.traceDisableEffects(record, disableEffects);
+ }
+ if (disableEffects == null
&& (!(record.isUpdate
&& (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
&& (record.getUserId() == UserHandle.USER_ALL ||
@@ -2657,6 +2674,26 @@
}
}
+ private static String callStateToString(int state) {
+ switch (state) {
+ case TelephonyManager.CALL_STATE_IDLE: return "CALL_STATE_IDLE";
+ case TelephonyManager.CALL_STATE_RINGING: return "CALL_STATE_RINGING";
+ case TelephonyManager.CALL_STATE_OFFHOOK: return "CALL_STATE_OFFHOOK";
+ default: return "CALL_STATE_UNKNOWN_" + state;
+ }
+ }
+
+ private void listenForCallState() {
+ TelephonyManager.from(getContext()).listen(new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (mCallState == state) return;
+ if (DBG) Slog.d(TAG, "Call state changed: " + callStateToString(state));
+ mCallState = state;
+ }
+ }, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+
/**
* Generates a NotificationRankingUpdate from 'sbns', considering only
* notifications visible to the given listener.
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index f84409e..6cc5e0e 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -55,6 +55,7 @@
private static final int TYPE_CONFIG = 10;
private static final int TYPE_FOLLOW_RINGER_MODE = 11;
private static final int TYPE_NOT_INTERCEPTED = 12;
+ private static final int TYPE_DISABLE_EFFECTS = 13;
private static int sNext;
private static int sSize;
@@ -106,6 +107,10 @@
+ zenModeToString(oldZen) + " -> " + zenModeToString(newZen));
}
+ public static void traceDisableEffects(NotificationRecord record, String reason) {
+ append(TYPE_DISABLE_EFFECTS, record.getKey() + "," + reason);
+ }
+
private static String subscribeResult(IConditionProvider provider, RemoteException e) {
return provider == null ? "no provider" : e != null ? e.getMessage() : "ok";
}
@@ -124,6 +129,7 @@
case TYPE_CONFIG: return "config";
case TYPE_FOLLOW_RINGER_MODE: return "follow_ringer_mode";
case TYPE_NOT_INTERCEPTED: return "not_intercepted";
+ case TYPE_DISABLE_EFFECTS: return "disable_effects";
default: return "unknown";
}
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index e6007bf..5bc1ff9 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -350,9 +350,9 @@
return record.isCategory(Notification.CATEGORY_EVENT);
}
- private boolean isCall(NotificationRecord record) {
- return isDefaultPhoneApp(record.sbn.getPackageName())
- || record.isCategory(Notification.CATEGORY_CALL);
+ public boolean isCall(NotificationRecord record) {
+ return record != null && (isDefaultPhoneApp(record.sbn.getPackageName())
+ || record.isCategory(Notification.CATEGORY_CALL));
}
private boolean isDefaultPhoneApp(String pkg) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 851cf17..50cb5fc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5960,11 +5960,19 @@
if (bp != null && !Objects.equals(bp.sourcePackage, p.info.packageName)) {
final boolean currentOwnerIsSystem = (bp.perm != null
&& isSystemApp(bp.perm.owner));
- if (isSystemApp(p.owner) && !currentOwnerIsSystem) {
- String msg = "New decl " + p.owner + " of permission "
- + p.info.name + " is system; overriding " + bp.sourcePackage;
- reportSettingsProblem(Log.WARN, msg);
- bp = null;
+ if (isSystemApp(p.owner)) {
+ if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
+ // It's a built-in permission and no owner, take ownership now
+ bp.packageSetting = pkgSetting;
+ bp.perm = p;
+ bp.uid = pkg.applicationInfo.uid;
+ bp.sourcePackage = p.info.packageName;
+ } else if (!currentOwnerIsSystem) {
+ String msg = "New decl " + p.owner + " of permission "
+ + p.info.name + " is system; overriding " + bp.sourcePackage;
+ reportSettingsProblem(Log.WARN, msg);
+ bp = null;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0c51160..30589b1 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -162,7 +162,7 @@
}
TaskStack getHomeStack() {
- if (mHomeStack == null) {
+ if (mHomeStack == null && mDisplayId == Display.DEFAULT_DISPLAY) {
Slog.e(TAG, "getHomeStack: Returning null from this=" + this);
}
return mHomeStack;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 89d2dc0..b4d429a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -584,6 +584,7 @@
* @param account The complete {@link PhoneAccount}.
* @hide
*/
+ @SystemApi
public void registerPhoneAccount(PhoneAccount account) {
try {
if (isServiceConnected()) {
@@ -600,6 +601,7 @@
* @param accountHandle A {@link PhoneAccountHandle} for the {@link PhoneAccount} to unregister.
* @hide
*/
+ @SystemApi
public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
try {
if (isServiceConnected()) {
@@ -800,6 +802,7 @@
* {@link ConnectionService#onCreateIncomingConnection}.
* @hide
*/
+ @SystemApi
public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
try {
if (isServiceConnected()) {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1ee390f..8e43772 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -146,6 +146,8 @@
* @hide
*/
public static final int RIL_RADIO_TECHNOLOGY_GSM = 16;
+ /** @hide */
+ public static final int RIL_RADIO_TECHNOLOGY_TD_SCDMA = 17;
/**
* Available registration states for GSM, UMTS and CDMA.
@@ -859,6 +861,7 @@
|| radioTechnology == RIL_RADIO_TECHNOLOGY_EVDO_0
|| radioTechnology == RIL_RADIO_TECHNOLOGY_EVDO_A
|| radioTechnology == RIL_RADIO_TECHNOLOGY_EVDO_B
- || radioTechnology == RIL_RADIO_TECHNOLOGY_EHRPD;
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_EHRPD
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_TD_SCDMA;
}
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 4f5f31a..5514798 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1222,18 +1222,15 @@
if (allowCached && mCachedConfigKey != null) {
key = mCachedConfigKey;
} else {
- key = this.SSID;
- if (key == null)
- key = "";
- if (this.wepKeys[0] != null) {
- key = key + "-WEP";
- }
- if (this.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
- key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK];
- }
- if (this.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
- this.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
- key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP];
+ if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
+ key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
+ } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
+ allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+ key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
+ } else if (wepKeys[0] != null) {
+ key = SSID + "WEP";
+ } else {
+ key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
}
mCachedConfigKey = key;
}