Merge "Add Device/Profile Owner gated apis for setting/getting blocked packages."
diff --git a/api/current.txt b/api/current.txt
index 4734ad3..96d6cc3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4424,6 +4424,8 @@
ctor public Notification(android.os.Parcel);
method public android.app.Notification clone();
method public int describeContents();
+ method public java.lang.String getGroup();
+ method public java.lang.String getSortKey();
method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
method public void writeToParcel(android.os.Parcel, int);
field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4466,6 +4468,7 @@
field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
+ field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
field public static final deprecated int FLAG_HIGH_PRIORITY = 128; // 0x80
field public static final int FLAG_INSISTENT = 4; // 0x4
field public static final int FLAG_LOCAL_ONLY = 256; // 0x100
@@ -4516,6 +4519,7 @@
method public android.app.Notification.Action clone();
method public int describeContents();
method public android.os.Bundle getExtras();
+ method public android.app.RemoteInput[] getRemoteInputs();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public android.app.PendingIntent actionIntent;
@@ -4523,14 +4527,20 @@
field public java.lang.CharSequence title;
}
- public static class Notification.Action.Builder {
+ public static final class Notification.Action.Builder {
ctor public Notification.Action.Builder(int, java.lang.CharSequence, android.app.PendingIntent);
ctor public Notification.Action.Builder(android.app.Notification.Action);
method public android.app.Notification.Action.Builder addExtras(android.os.Bundle);
+ method public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput);
+ method public android.app.Notification.Action.Builder apply(android.app.Notification.Action.Builder.Extender);
method public android.app.Notification.Action build();
method public android.os.Bundle getExtras();
}
+ public static abstract interface Notification.Action.Builder.Extender {
+ method public abstract android.app.Notification.Action.Builder applyTo(android.app.Notification.Action.Builder);
+ }
+
public static class Notification.BigPictureStyle extends android.app.Notification.Style {
ctor public Notification.BigPictureStyle();
ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
@@ -4554,6 +4564,7 @@
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
+ method public android.app.Notification.Builder apply(android.app.Notification.Builder.Extender);
method public android.app.Notification build();
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
@@ -4569,6 +4580,8 @@
method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
method public android.app.Notification.Builder setExtras(android.os.Bundle);
method public android.app.Notification.Builder setFullScreenIntent(android.app.PendingIntent, boolean);
+ method public android.app.Notification.Builder setGroup(java.lang.String);
+ method public android.app.Notification.Builder setGroupSummary(boolean);
method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
method public android.app.Notification.Builder setLights(int, int, int);
method public android.app.Notification.Builder setLocalOnly(boolean);
@@ -4581,6 +4594,7 @@
method public android.app.Notification.Builder setShowWhen(boolean);
method public android.app.Notification.Builder setSmallIcon(int);
method public android.app.Notification.Builder setSmallIcon(int, int);
+ method public android.app.Notification.Builder setSortKey(java.lang.String);
method public android.app.Notification.Builder setSound(android.net.Uri);
method public android.app.Notification.Builder setSound(android.net.Uri, int);
method public android.app.Notification.Builder setStyle(android.app.Notification.Style);
@@ -4593,6 +4607,10 @@
method public android.app.Notification.Builder setWhen(long);
}
+ public static abstract interface Notification.Builder.Extender {
+ method public abstract android.app.Notification.Builder applyTo(android.app.Notification.Builder);
+ }
+
public static class Notification.InboxStyle extends android.app.Notification.Style {
ctor public Notification.InboxStyle();
ctor public Notification.InboxStyle(android.app.Notification.Builder);
@@ -4696,6 +4714,31 @@
field public static final int STYLE_SPINNER = 0; // 0x0
}
+ public final class RemoteInput implements android.os.Parcelable {
+ method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
+ method public int describeContents();
+ method public boolean getAllowFreeFormInput();
+ method public java.lang.CharSequence[] getChoices();
+ method public android.os.Bundle getExtras();
+ method public java.lang.CharSequence getLabel();
+ method public java.lang.String getResultKey();
+ method public static android.os.Bundle getResultsFromIntent(android.content.Intent);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final java.lang.String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+ field public static final java.lang.String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+ }
+
+ public static final class RemoteInput.Builder {
+ ctor public RemoteInput.Builder(java.lang.String);
+ method public android.app.RemoteInput.Builder addExtras(android.os.Bundle);
+ method public android.app.RemoteInput build();
+ method public android.os.Bundle getExtras();
+ method public android.app.RemoteInput.Builder setAllowFreeFormInput(boolean);
+ method public android.app.RemoteInput.Builder setChoices(java.lang.CharSequence[]);
+ method public android.app.RemoteInput.Builder setLabel(java.lang.CharSequence);
+ }
+
public class SearchManager implements android.content.DialogInterface.OnCancelListener android.content.DialogInterface.OnDismissListener {
method public android.content.ComponentName getGlobalSearchActivity();
method public android.app.SearchableInfo getSearchableInfo(android.content.ComponentName);
@@ -5065,6 +5108,7 @@
method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
method public int setApplicationsBlocked(android.content.ComponentName, android.content.Intent, boolean);
method public void setCameraDisabled(android.content.ComponentName, boolean);
+ method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskComponents(android.content.ComponentName[]) throws java.lang.SecurityException;
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -5080,6 +5124,7 @@
method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
method public void setPasswordQuality(android.content.ComponentName, int);
method public void setProfileEnabled(android.content.ComponentName);
+ method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
@@ -14939,6 +14984,7 @@
ctor public RemoteControlClient(android.app.PendingIntent);
ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper);
method public android.media.RemoteControlClient.MetadataEditor editMetadata(boolean);
+ method public android.media.session.MediaSession getMediaSession();
method public void setMetadataUpdateListener(android.media.RemoteControlClient.OnMetadataUpdateListener);
method public void setOnGetPlaybackPositionListener(android.media.RemoteControlClient.OnGetPlaybackPositionListener);
method public void setPlaybackPositionUpdateListener(android.media.RemoteControlClient.OnPlaybackPositionUpdateListener);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fd76b9c4..59b3a27 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -45,6 +45,7 @@
import java.lang.annotation.RetentionPolicy;
import java.text.NumberFormat;
import java.util.ArrayList;
+import java.util.Collections;
/**
* A class that represents how a persistent notification is to be presented to
@@ -370,6 +371,14 @@
*/
public static final int FLAG_LOCAL_ONLY = 0x00000100;
+ /**
+ * Bit to be bitswise-ored into the {@link #flags} field that should be
+ * set if this notification is the group summary for a group of notifications.
+ * Grouped notifications may display in a cluster or stack on devices which
+ * support such rendering. Requires a group key also be set using {@link Builder#setGroup}.
+ */
+ public static final int FLAG_GROUP_SUMMARY = 0x00000200;
+
public int flags;
/** @hide */
@@ -539,6 +548,34 @@
*/
public String category;
+ private String mGroupKey;
+
+ /**
+ * Get the key used to group this notification into a cluster or stack
+ * with other notifications on devices which support such rendering.
+ */
+ public String getGroup() {
+ return mGroupKey;
+ }
+
+ private String mSortKey;
+
+ /**
+ * Get a sort key that orders this notification among other notifications from the
+ * same package. This can be useful if an external sort was already applied and an app
+ * would like to preserve this. Notifications will be sorted lexicographically using this
+ * value, although providing different priorities in addition to providing sort key may
+ * cause this value to be ignored.
+ *
+ * <p>This sort key can also be used to order members of a notification group. See
+ * {@link Builder#setGroup}.
+ *
+ * @see String#compareTo(String)
+ */
+ public String getSortKey() {
+ return mSortKey;
+ }
+
/**
* Additional semantic data to be carried around with this Notification.
* <p>
@@ -706,15 +743,18 @@
*/
public static class Action implements Parcelable {
private final Bundle mExtras;
+ private RemoteInput[] mRemoteInputs;
/**
* Small icon representing the action.
*/
public int icon;
+
/**
* Title of the action.
*/
public CharSequence title;
+
/**
* Intent to send when the user invokes this action. May be null, in which case the action
* may be rendered in a disabled presentation by the system UI.
@@ -728,19 +768,23 @@
actionIntent = PendingIntent.CREATOR.createFromParcel(in);
}
mExtras = in.readBundle();
+ mRemoteInputs = in.createTypedArray(RemoteInput.CREATOR);
}
+
/**
* Use {@link Notification.Builder#addAction(int, CharSequence, PendingIntent)}.
*/
public Action(int icon, CharSequence title, PendingIntent intent) {
- this(icon, title, intent, new Bundle());
+ this(icon, title, intent, new Bundle(), null);
}
- private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+ private Action(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+ RemoteInput[] remoteInputs) {
this.icon = icon;
this.title = title;
this.actionIntent = intent;
this.mExtras = extras != null ? extras : new Bundle();
+ this.mRemoteInputs = remoteInputs;
}
/**
@@ -751,13 +795,22 @@
}
/**
+ * Get the list of inputs to be collected from the user when this action is sent.
+ * May return null if no remote inputs were added.
+ */
+ public RemoteInput[] getRemoteInputs() {
+ return mRemoteInputs;
+ }
+
+ /**
* Builder class for {@link Action} objects.
*/
- public static class Builder {
+ public static final class Builder {
private final int mIcon;
private final CharSequence mTitle;
private final PendingIntent mIntent;
private final Bundle mExtras;
+ private ArrayList<RemoteInput> mRemoteInputs;
/**
* Construct a new builder for {@link Action} object.
@@ -766,7 +819,7 @@
* @param intent the {@link PendingIntent} to fire when users trigger this action
*/
public Builder(int icon, CharSequence title, PendingIntent intent) {
- this(icon, title, intent, new Bundle());
+ this(icon, title, intent, new Bundle(), null);
}
/**
@@ -775,14 +828,20 @@
* @param action the action to read fields from.
*/
public Builder(Action action) {
- this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras));
+ this(action.icon, action.title, action.actionIntent, new Bundle(action.mExtras),
+ action.getRemoteInputs());
}
- private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras) {
+ private Builder(int icon, CharSequence title, PendingIntent intent, Bundle extras,
+ RemoteInput[] remoteInputs) {
mIcon = icon;
mTitle = title;
mIntent = intent;
mExtras = extras;
+ if (remoteInputs != null) {
+ mRemoteInputs = new ArrayList<RemoteInput>(remoteInputs.length);
+ Collections.addAll(mRemoteInputs, remoteInputs);
+ }
}
/**
@@ -809,22 +868,62 @@
}
/**
+ * Add an input to be collected from the user when this action is sent.
+ * Response values can be retrieved from the fired intent by using the
+ * {@link RemoteInput#getResultsFromIntent} function.
+ * @param remoteInput a {@link RemoteInput} to add to the action
+ * @return this object for method chaining
+ */
+ public Builder addRemoteInput(RemoteInput remoteInput) {
+ if (mRemoteInputs == null) {
+ mRemoteInputs = new ArrayList<RemoteInput>();
+ }
+ mRemoteInputs.add(remoteInput);
+ return this;
+ }
+
+ /**
+ * Apply an extender to this action builder. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public Builder apply(Extender extender) {
+ extender.applyTo(this);
+ return this;
+ }
+
+ /**
+ * Extender interface for use with {@link #apply}. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public interface Extender {
+ /**
+ * Apply this extender to a notification action builder.
+ * @param builder the builder to be modified.
+ * @return the build object for chaining.
+ */
+ public Builder applyTo(Builder builder);
+ }
+
+ /**
* Combine all of the options that have been set and return a new {@link Action}
* object.
* @return the built action
*/
public Action build() {
- return new Action(mIcon, mTitle, mIntent, mExtras);
+ RemoteInput[] remoteInputs = mRemoteInputs != null
+ ? mRemoteInputs.toArray(new RemoteInput[mRemoteInputs.size()]) : null;
+ return new Action(mIcon, mTitle, mIntent, mExtras, remoteInputs);
}
}
@Override
public Action clone() {
return new Action(
- this.icon,
- this.title,
- this.actionIntent, // safe to alias
- new Bundle(this.mExtras));
+ icon,
+ title,
+ actionIntent, // safe to alias
+ new Bundle(mExtras),
+ getRemoteInputs());
}
@Override
public int describeContents() {
@@ -841,6 +940,7 @@
out.writeInt(0);
}
out.writeBundle(mExtras);
+ out.writeTypedArray(mRemoteInputs, flags);
}
public static final Parcelable.Creator<Action> CREATOR =
new Parcelable.Creator<Action>() {
@@ -960,6 +1060,10 @@
category = parcel.readString();
+ mGroupKey = parcel.readString();
+
+ mSortKey = parcel.readString();
+
extras = parcel.readBundle(); // may be null
actions = parcel.createTypedArray(Action.CREATOR); // may be null
@@ -1037,6 +1141,10 @@
that.category = this.category;
+ that.mGroupKey = this.mGroupKey;
+
+ that.mSortKey = this.mSortKey;
+
if (this.extras != null) {
try {
that.extras = new Bundle(this.extras);
@@ -1188,6 +1296,10 @@
parcel.writeString(category);
+ parcel.writeString(mGroupKey);
+
+ parcel.writeString(mSortKey);
+
parcel.writeBundle(extras); // null ok
parcel.writeTypedArray(actions, 0); // null ok
@@ -1325,7 +1437,18 @@
sb.append(" flags=0x");
sb.append(Integer.toHexString(this.flags));
sb.append(String.format(" color=0x%08x", this.color));
- sb.append(" category="); sb.append(this.category);
+ if (this.category != null) {
+ sb.append(" category=");
+ sb.append(this.category);
+ }
+ if (this.mGroupKey != null) {
+ sb.append(" groupKey=");
+ sb.append(this.mGroupKey);
+ }
+ if (this.mSortKey != null) {
+ sb.append(" sortKey=");
+ sb.append(this.mSortKey);
+ }
if (actions != null) {
sb.append(" ");
sb.append(actions.length);
@@ -1408,6 +1531,8 @@
private int mProgress;
private boolean mProgressIndeterminate;
private String mCategory;
+ private String mGroupKey;
+ private String mSortKey;
private Bundle mExtras;
private int mPriority;
private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
@@ -1839,6 +1964,51 @@
}
/**
+ * Set this notification to be part of a group of notifications sharing the same key.
+ * Grouped notifications may display in a cluster or stack on devices which
+ * support such rendering.
+ *
+ * <p>To make this notification the summary for its group, also call
+ * {@link #setGroupSummary}. A sort order can be specified for group members by using
+ * {@link #setSortKey}.
+ * @param groupKey The group key of the group.
+ * @return this object for method chaining
+ */
+ public Builder setGroup(String groupKey) {
+ mGroupKey = groupKey;
+ return this;
+ }
+
+ /**
+ * Set this notification to be the group summary for a group of notifications.
+ * Grouped notifications may display in a cluster or stack on devices which
+ * support such rendering. Requires a group key also be set using {@link #setGroup}.
+ * @param isGroupSummary Whether this notification should be a group summary.
+ * @return this object for method chaining
+ */
+ public Builder setGroupSummary(boolean isGroupSummary) {
+ setFlag(FLAG_GROUP_SUMMARY, isGroupSummary);
+ return this;
+ }
+
+ /**
+ * Set a sort key that orders this notification among other notifications from the
+ * same package. This can be useful if an external sort was already applied and an app
+ * would like to preserve this. Notifications will be sorted lexicographically using this
+ * value, although providing different priorities in addition to providing sort key may
+ * cause this value to be ignored.
+ *
+ * <p>This sort key can also be used to order members of a notification group. See
+ * {@link #setGroup}.
+ *
+ * @see String#compareTo(String)
+ */
+ public Builder setSortKey(String sortKey) {
+ mSortKey = sortKey;
+ return this;
+ }
+
+ /**
* Merge additional metadata into this notification.
*
* <p>Values within the Bundle will replace existing extras values in this Builder.
@@ -1949,7 +2119,7 @@
/**
* Specify the value of {@link #visibility}.
-
+ *
* @param visibility One of {@link #VISIBILITY_PRIVATE} (the default),
* {@link #VISIBILITY_SECRET}, or {@link #VISIBILITY_PUBLIC}.
*
@@ -1971,6 +2141,28 @@
return this;
}
+ /**
+ * Apply an extender to this notification builder. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public Builder apply(Extender extender) {
+ extender.applyTo(this);
+ return this;
+ }
+
+ /**
+ * Extender interface for use with {@link #apply}. Extenders may be used to add
+ * metadata or change options on this builder.
+ */
+ public interface Extender {
+ /**
+ * Apply this extender to a notification builder.
+ * @param builder the builder to be modified.
+ * @return the build object for chaining.
+ */
+ public Builder applyTo(Builder builder);
+ }
+
private void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
@@ -2298,6 +2490,8 @@
n.flags |= FLAG_SHOW_LIGHTS;
}
n.category = mCategory;
+ n.mGroupKey = mGroupKey;
+ n.mSortKey = mSortKey;
n.priority = mPriority;
if (mActions.size() > 0) {
n.actions = new Action[mActions.size()];
diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java
new file mode 100644
index 0000000..9cfc541
--- /dev/null
+++ b/core/java/android/app/RemoteInput.java
@@ -0,0 +1,297 @@
+/*
+ * 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 android.app;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A {@code RemoteInput} object specifies input to be collected from a user to be passed along with
+ * an intent inside a {@link android.app.PendingIntent} that is sent.
+ * Always use {@link RemoteInput.Builder} to create instances of this class.
+ * <p class="note"> See
+ * <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from
+ * a Notification</a> for more information on how to use this class.
+ *
+ * <p>The following example adds a {@code RemoteInput} to a {@link Notification.Action},
+ * sets the result key as {@code quick_reply}, and sets the label as {@code Quick reply}.
+ * Users are prompted to input a response when they trigger the action. The results are sent along
+ * with the intent and can be retrieved with the result key (provided to the {@link Builder}
+ * constructor) from the Bundle returned by {@link #getResultsFromIntent}.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Notification.Action action = new Notification.Action.Builder(
+ * R.drawable.reply, "Reply", actionIntent)
+ * <b>.addRemoteInput(new RemoteInput.Builder(KEY_QUICK_REPLY_TEXT)
+ * .setLabel("Quick reply").build()</b>)
+ * .build();</pre>
+ *
+ * <p>When the {@link android.app.PendingIntent} is fired, the intent inside will contain the
+ * input results if collected. To access these results, use the {@link #getResultsFromIntent}
+ * function. The result values will present under the result key passed to the {@link Builder}
+ * constructor.
+ *
+ * <pre class="prettyprint">
+ * public static final String KEY_QUICK_REPLY_TEXT = "quick_reply";
+ * Bundle results = RemoteInput.getResultsFromIntent(intent);
+ * if (results != null) {
+ * CharSequence quickReplyResult = results.getCharSequence(KEY_QUICK_REPLY_TEXT);
+ * }</pre>
+ */
+public final class RemoteInput implements Parcelable {
+ /** Label used to denote the clip data type used for remote input transport */
+ public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
+
+ /** Extra added to a clip data intent object to hold the results bundle. */
+ public static final String EXTRA_RESULTS_DATA = "android.remoteinput.resultsData";
+
+ private final String mResultKey;
+ private final CharSequence mLabel;
+ private final CharSequence[] mChoices;
+ private final boolean mAllowFreeFormInput;
+ private final Bundle mExtras;
+
+ private RemoteInput(String resultKey, CharSequence label, CharSequence[] choices,
+ boolean allowFreeFormInput, Bundle extras) {
+ this.mResultKey = resultKey;
+ this.mLabel = label;
+ this.mChoices = choices;
+ this.mAllowFreeFormInput = allowFreeFormInput;
+ this.mExtras = extras;
+ }
+
+ /**
+ * Get the key that the result of this input will be set in from the Bundle returned by
+ * {@link #getResultsFromIntent} when the {@link android.app.PendingIntent} is sent.
+ */
+ public String getResultKey() {
+ return mResultKey;
+ }
+
+ /**
+ * Get the label to display to users when collecting this input.
+ */
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Get possible input choices. This can be {@code null} if there are no choices to present.
+ */
+ public CharSequence[] getChoices() {
+ return mChoices;
+ }
+
+ /**
+ * Get whether or not users can provide an arbitrary value for
+ * input. If you set this to {@code false}, users must select one of the
+ * choices in {@link #getChoices}. An {@link IllegalArgumentException} is thrown
+ * if you set this to false and {@link #getChoices} returns {@code null} or empty.
+ */
+ public boolean getAllowFreeFormInput() {
+ return mAllowFreeFormInput;
+ }
+
+ /**
+ * Get additional metadata carried around with this remote input.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Builder class for {@link RemoteInput} objects.
+ */
+ public static final class Builder {
+ private final String mResultKey;
+ private CharSequence mLabel;
+ private CharSequence[] mChoices;
+ private boolean mAllowFreeFormInput = true;
+ private Bundle mExtras = new Bundle();
+
+ /**
+ * Create a builder object for {@link RemoteInput} objects.
+ * @param resultKey the Bundle key that refers to this input when collected from the user
+ */
+ public Builder(String resultKey) {
+ if (resultKey == null) {
+ throw new IllegalArgumentException("Result key can't be null");
+ }
+ mResultKey = resultKey;
+ }
+
+ /**
+ * Set a label to be displayed to the user when collecting this input.
+ * @param label The label to show to users when they input a response.
+ * @return this object for method chaining
+ */
+ public Builder setLabel(CharSequence label) {
+ mLabel = Notification.safeCharSequence(label);
+ return this;
+ }
+
+ /**
+ * Specifies choices available to the user to satisfy this input.
+ * @param choices an array of pre-defined choices for users input.
+ * You must provide a non-null and non-empty array if
+ * you disabled free form input using {@link #setAllowFreeFormInput}.
+ * @return this object for method chaining
+ */
+ public Builder setChoices(CharSequence[] choices) {
+ if (choices == null) {
+ mChoices = null;
+ } else {
+ mChoices = new CharSequence[choices.length];
+ for (int i = 0; i < choices.length; i++) {
+ mChoices[i] = Notification.safeCharSequence(choices[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Specifies whether the user can provide arbitrary values.
+ *
+ * @param allowFreeFormInput The default is {@code true}.
+ * If you specify {@code false}, you must provide a non-null
+ * and non-empty array to {@link #setChoices} or an
+ * {@link IllegalArgumentException} is thrown.
+ * @return this object for method chaining
+ */
+ public Builder setAllowFreeFormInput(boolean allowFreeFormInput) {
+ mAllowFreeFormInput = allowFreeFormInput;
+ return this;
+ }
+
+ /**
+ * Merge additional metadata into this builder.
+ *
+ * <p>Values within the Bundle will replace existing extras values in this Builder.
+ *
+ * @see RemoteInput#getExtras
+ */
+ public Builder addExtras(Bundle extras) {
+ if (extras != null) {
+ mExtras.putAll(extras);
+ }
+ return this;
+ }
+
+ /**
+ * Get the metadata Bundle used by this Builder.
+ *
+ * <p>The returned Bundle is shared with this Builder.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Combine all of the options that have been set and return a new {@link RemoteInput}
+ * object.
+ */
+ public RemoteInput build() {
+ return new RemoteInput(mResultKey, mLabel, mChoices, mAllowFreeFormInput, mExtras);
+ }
+ }
+
+ private RemoteInput(Parcel in) {
+ mResultKey = in.readString();
+ mLabel = in.readCharSequence();
+ mChoices = in.readCharSequenceArray();
+ mAllowFreeFormInput = in.readInt() != 0;
+ mExtras = in.readBundle();
+ }
+
+ /**
+ * Get the remote input results bundle from an intent. The returned Bundle will
+ * contain a key/value for every result key populated by remote input collector.
+ * Use the {@link Bundle#getCharSequence(String)} method to retrieve a value.
+ * @param intent The intent object that fired in response to an action or content intent
+ * which also had one or more remote input requested.
+ */
+ public static Bundle getResultsFromIntent(Intent intent) {
+ ClipData clipData = intent.getClipData();
+ if (clipData == null) {
+ return null;
+ }
+ ClipDescription clipDescription = clipData.getDescription();
+ if (!clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)) {
+ return null;
+ }
+ if (clipDescription.getLabel().equals(RESULTS_CLIP_LABEL)) {
+ return clipData.getItemAt(0).getIntent().getExtras().getParcelable(EXTRA_RESULTS_DATA);
+ }
+ return null;
+ }
+
+ /**
+ * Populate an intent object with the results gathered from remote input. This method
+ * should only be called by remote input collection services when sending results to a
+ * pending intent.
+ * @param remoteInputs The remote inputs for which results are being provided
+ * @param intent The intent to add remote inputs to. The {@link ClipData}
+ * field of the intent will be modified to contain the results.
+ * @param results A bundle holding the remote input results. This bundle should
+ * be populated with keys matching the result keys specified in
+ * {@code remoteInputs} with values being the result per key.
+ */
+ public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
+ Bundle results) {
+ Bundle resultsBundle = new Bundle();
+ for (RemoteInput remoteInput : remoteInputs) {
+ Object result = results.get(remoteInput.getResultKey());
+ if (result instanceof CharSequence) {
+ resultsBundle.putCharSequence(remoteInput.getResultKey(), (CharSequence) result);
+ }
+ }
+ Intent clipIntent = new Intent();
+ clipIntent.putExtra(EXTRA_RESULTS_DATA, resultsBundle);
+ intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipIntent));
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mResultKey);
+ out.writeCharSequence(mLabel);
+ out.writeCharSequenceArray(mChoices);
+ out.writeInt(mAllowFreeFormInput ? 1 : 0);
+ out.writeBundle(mExtras);
+ }
+
+ public static final Creator<RemoteInput> CREATOR = new Creator<RemoteInput>() {
+ @Override
+ public RemoteInput createFromParcel(Parcel in) {
+ return new RemoteInput(in);
+ }
+
+ @Override
+ public RemoteInput[] newArray(int size) {
+ return new RemoteInput[size];
+ }
+ };
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index c727a80..18e2a95 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.provider.Settings;
import android.service.trust.TrustAgentService;
import android.util.Log;
@@ -2243,4 +2244,42 @@
}
return false;
}
+
+ /**
+ * Called by device owners to update {@link Settings.Global} settings. Validation that the value
+ * of the setting is in the correct form for the setting type should be performed by the caller.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param setting The name of the setting to update.
+ * @param value The value to update the setting to.
+ */
+ public void setGlobalSetting(ComponentName admin, String setting, String value) {
+ if (mService != null) {
+ try {
+ mService.setGlobalSetting(admin, setting, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
+ * Called by profile or device owners to update {@link Settings.Secure} settings. Validation
+ * that the value of the setting is in the correct form for the setting type should be performed
+ * by the caller.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param setting The name of the setting to update.
+ * @param value The value to update the setting to.
+ */
+ public void setSecureSetting(ComponentName admin, String setting, String value) {
+ if (mService != null) {
+ try {
+ mService.setSecureSetting(admin, setting, value);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 278a612..7257158 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -137,4 +137,7 @@
void setLockTaskComponents(in ComponentName[] components);
ComponentName[] getLockTaskComponents();
boolean isLockTaskPermitted(in ComponentName component);
+
+ void setGlobalSetting(in ComponentName who, in String setting, in String value);
+ void setSecureSetting(in ComponentName who, in String setting, in String value);
}
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 5674154..3f01dd2 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -64,7 +64,6 @@
* List Resource</a>.</p>
*/
public class ColorStateList implements Parcelable {
-
private int[][] mStateSpecs; // must be parallel to mColors
private int[] mColors; // must be parallel to mStateSpecs
private int mDefaultColor = 0xffff0000;
@@ -100,9 +99,9 @@
public static ColorStateList valueOf(int color) {
// TODO: should we collect these eventually?
synchronized (sCache) {
- WeakReference<ColorStateList> ref = sCache.get(color);
- ColorStateList csl = ref != null ? ref.get() : null;
+ final WeakReference<ColorStateList> ref = sCache.get(color);
+ ColorStateList csl = ref != null ? ref.get() : null;
if (csl != null) {
return csl;
}
@@ -118,8 +117,7 @@
*/
public static ColorStateList createFromXml(Resources r, XmlPullParser parser)
throws XmlPullParserException, IOException {
-
- AttributeSet attrs = Xml.asAttributeSet(parser);
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.START_TAG
@@ -133,22 +131,22 @@
return createFromXmlInner(r, parser, attrs);
}
- /* Create from inside an XML document. Called on a parser positioned at
- * a tag in an XML document, tries to create a ColorStateList from that tag.
- * Returns null if the tag is not a valid ColorStateList.
+ /**
+ * Create from inside an XML document. Called on a parser positioned at a
+ * tag in an XML document, tries to create a ColorStateList from that tag.
+ *
+ * @throws XmlPullParserException if the current tag is not <selector>
+ * @return A color state list for the current tag.
*/
private static ColorStateList createFromXmlInner(Resources r, XmlPullParser parser,
AttributeSet attrs) throws XmlPullParserException, IOException {
-
- ColorStateList colorStateList;
-
+ final ColorStateList colorStateList;
final String name = parser.getName();
-
if (name.equals("selector")) {
colorStateList = new ColorStateList();
} else {
throw new XmlPullParserException(
- parser.getPositionDescription() + ": invalid drawable tag " + name);
+ parser.getPositionDescription() + ": invalid drawable tag " + name);
}
colorStateList.inflate(r, parser, attrs);
@@ -161,9 +159,8 @@
* (0-255).
*/
public ColorStateList withAlpha(int alpha) {
- int[] colors = new int[mColors.length];
-
- int len = colors.length;
+ final int[] colors = new int[mColors.length];
+ final int len = colors.length;
for (int i = 0; i < len; i++) {
colors[i] = (mColors[i] & 0xFFFFFF) | (alpha << 24);
}
@@ -176,7 +173,6 @@
*/
private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
throws XmlPullParserException, IOException {
-
int type;
final int innerDepth = parser.getDepth()+1;
@@ -259,10 +255,25 @@
System.arraycopy(stateSpecList, 0, mStateSpecs, 0, listSize);
}
+ /**
+ * Indicates whether this color state list contains more than one state spec
+ * and will change color based on state.
+ *
+ * @return True if this color state list changes color based on state, false
+ * otherwise.
+ * @see #getColorForState(int[], int)
+ */
public boolean isStateful() {
return mStateSpecs.length > 1;
}
+ /**
+ * Indicates whether this color state list is opaque, which means that every
+ * color returned from {@link #getColorForState(int[], int)} has an alpha
+ * value of 255.
+ *
+ * @return True if this color state list is opaque.
+ */
public boolean isOpaque() {
final int n = mColors.length;
for (int i = 0; i < n; i++) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 1692a79..a78f8e2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.Nullable;
import android.content.pm.ActivityInfo;
import android.graphics.Movie;
import android.graphics.drawable.Drawable;
@@ -719,12 +720,12 @@
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
* entry. The value 0 is an invalid identifier.
- * @param theme The theme used to style the drawable attributes.
+ * @param theme The theme used to style the drawable attributes, may be {@code null}.
* @return Drawable An object that can be used to draw this resource.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
*/
- public Drawable getDrawable(int id, Theme theme) throws NotFoundException {
+ public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -777,12 +778,12 @@
* The value 0 is an invalid identifier.
* @param density The desired screen density indicated by the resource as
* found in {@link DisplayMetrics}.
- * @param theme The theme used to style the drawable attributes.
+ * @param theme The theme used to style the drawable attributes, may be {@code null}.
* @return Drawable An object that can be used to draw this resource.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
*/
- public Drawable getDrawableForDensity(int id, int density, Theme theme) {
+ public Drawable getDrawableForDensity(int id, int density, @Nullable Theme theme) {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 0bd46bc..b17f502 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -115,7 +115,7 @@
if (count > 0 && selStart == selEnd && selStart > 0) {
char c = content.charAt(selStart - 1);
- if (c == i || c == Character.toUpperCase(i) && view != null) {
+ if ((c == i || c == Character.toUpperCase(i)) && view != null) {
if (showCharacterPicker(view, content, c, false, count)) {
resetMetaState(content);
return true;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 3eabc3a..911fb96 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -512,13 +512,12 @@
}
/**
- * Indicates whether this view will change its appearance based on state.
- * Clients can use this to determine whether it is necessary to calculate
- * their state and call setState.
+ * Indicates whether this drawable will change its appearance based on
+ * state. Clients can use this to determine whether it is necessary to
+ * calculate their state and call setState.
*
- * @return True if this view changes its appearance based on state, false
- * otherwise.
- *
+ * @return True if this drawable changes its appearance based on state,
+ * false otherwise.
* @see #setState(int[])
*/
public boolean isStateful() {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3a3f76d..575667d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2557,60 +2557,191 @@
// class is not used by other parts of the framework, which instead use definitions and methods
// from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService.
- /** {@hide} The audio output device code for the small speaker at the front of the device used
+ /** @hide
+ * The audio output device code for the small speaker at the front of the device used
* when placing calls. Does not refer to an in-ear headphone without attached microphone,
* such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a
* {@link #DEVICE_OUT_WIRED_HEADPHONE}.
*/
public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE;
- /** {@hide} The audio output device code for the built-in speaker */
+ /** @hide
+ * The audio output device code for the built-in speaker */
public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER;
- /** {@hide} The audio output device code for a wired headset with attached microphone */
+ /** @hide
+ * The audio output device code for a wired headset with attached microphone */
public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
- /** {@hide} The audio output device code for a wired headphone without attached microphone */
+ /** @hide
+ * The audio output device code for a wired headphone without attached microphone */
public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
- /** {@hide} The audio output device code for generic Bluetooth SCO, for voice */
+ /** @hide
+ * The audio output device code for generic Bluetooth SCO, for voice */
public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
- /** {@hide} The audio output device code for Bluetooth SCO Headset Profile (HSP) and
- * Hands-Free Profile (HFP), for voice
+ /** @hide
+ * The audio output device code for Bluetooth SCO Headset Profile (HSP) and
+ * Hands-Free Profile (HFP), for voice
*/
public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET =
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- /** {@hide} The audio output device code for Bluetooth SCO car audio, for voice */
+ /** @hide
+ * The audio output device code for Bluetooth SCO car audio, for voice */
public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT =
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- /** {@hide} The audio output device code for generic Bluetooth A2DP, for music */
+ /** @hide
+ * The audio output device code for generic Bluetooth A2DP, for music */
public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
- /** {@hide} The audio output device code for Bluetooth A2DP headphones, for music */
+ /** @hide
+ * The audio output device code for Bluetooth A2DP headphones, for music */
public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES =
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- /** {@hide} The audio output device code for Bluetooth A2DP external speaker, for music */
+ /** @hide
+ * The audio output device code for Bluetooth A2DP external speaker, for music */
public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER =
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- /** {@hide} The audio output device code for S/PDIF or HDMI */
+ /** @hide
+ * The audio output device code for S/PDIF (legacy) or HDMI
+ * Deprecated: replaced by {@link #DEVICE_OUT_HDMI} */
public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL;
- /** {@hide} The audio output device code for an analog wired headset attached via a
+ /** @hide
+ * The audio output device code for HDMI */
+ public static final int DEVICE_OUT_HDMI = AudioSystem.DEVICE_OUT_HDMI;
+ /** @hide
+ * The audio output device code for an analog wired headset attached via a
* docking station
*/
public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
- /** {@hide} The audio output device code for a digital wired headset attached via a
+ /** @hide
+ * The audio output device code for a digital wired headset attached via a
* docking station
*/
public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
- /** {@hide} The audio output device code for a USB audio accessory. The accessory is in USB host
+ /** @hide
+ * The audio output device code for a USB audio accessory. The accessory is in USB host
* mode and the Android device in USB device mode
*/
public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
- /** {@hide} The audio output device code for a USB audio device. The device is in USB device
+ /** @hide
+ * The audio output device code for a USB audio device. The device is in USB device
* mode and the Android device in USB host mode
*/
public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE;
- /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be
+ /** @hide
+ * The audio output device code for projection output.
+ */
+ public static final int DEVICE_OUT_REMOTE_SUBMIX = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+ /** @hide
+ * The audio output device code the telephony voice TX path.
+ */
+ public static final int DEVICE_OUT_TELEPHONY_TX = AudioSystem.DEVICE_OUT_TELEPHONY_TX;
+ /** @hide
+ * The audio output device code for an analog jack with line impedance detected.
+ */
+ public static final int DEVICE_OUT_LINE = AudioSystem.DEVICE_OUT_LINE;
+ /** @hide
+ * The audio output device code for HDMI Audio Return Channel.
+ */
+ public static final int DEVICE_OUT_HDMI_ARC = AudioSystem.DEVICE_OUT_HDMI_ARC;
+ /** @hide
+ * The audio output device code for S/PDIF digital connection.
+ */
+ public static final int DEVICE_OUT_SPDIF = AudioSystem.DEVICE_OUT_SPDIF;
+ /** @hide
+ * The audio output device code for built-in FM transmitter.
+ */
+ public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM;
+ /** @hide
+ * This is not used as a returned value from {@link #getDevicesForStream}, but could be
* used in the future in a set method to select whatever default device is chosen by the
* platform-specific implementation.
*/
public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT;
+ /** @hide
+ * The audio input device code for default built-in microphone
+ */
+ public static final int DEVICE_IN_BUILTIN_MIC = AudioSystem.DEVICE_IN_BUILTIN_MIC;
+ /** @hide
+ * The audio input device code for a Bluetooth SCO headset
+ */
+ public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET =
+ AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ /** @hide
+ * The audio input device code for wired headset microphone
+ */
+ public static final int DEVICE_IN_WIRED_HEADSET =
+ AudioSystem.DEVICE_IN_WIRED_HEADSET;
+ /** @hide
+ * The audio input device code for HDMI
+ */
+ public static final int DEVICE_IN_HDMI =
+ AudioSystem.DEVICE_IN_HDMI;
+ /** @hide
+ * The audio input device code for telephony voice RX path
+ */
+ public static final int DEVICE_IN_TELEPHONY_RX =
+ AudioSystem.DEVICE_IN_TELEPHONY_RX;
+ /** @hide
+ * The audio input device code for built-in microphone pointing to the back
+ */
+ public static final int DEVICE_IN_BACK_MIC =
+ AudioSystem.DEVICE_IN_BACK_MIC;
+ /** @hide
+ * The audio input device code for analog from a docking station
+ */
+ public static final int DEVICE_IN_ANLG_DOCK_HEADSET =
+ AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET;
+ /** @hide
+ * The audio input device code for digital from a docking station
+ */
+ public static final int DEVICE_IN_DGTL_DOCK_HEADSET =
+ AudioSystem.DEVICE_IN_DGTL_DOCK_HEADSET;
+ /** @hide
+ * The audio input device code for a USB audio accessory. The accessory is in USB host
+ * mode and the Android device in USB device mode
+ */
+ public static final int DEVICE_IN_USB_ACCESSORY =
+ AudioSystem.DEVICE_IN_USB_ACCESSORY;
+ /** @hide
+ * The audio input device code for a USB audio device. The device is in USB device
+ * mode and the Android device in USB host mode
+ */
+ public static final int DEVICE_IN_USB_DEVICE =
+ AudioSystem.DEVICE_IN_USB_DEVICE;
+ /** @hide
+ * The audio input device code for a FM radio tuner
+ */
+ public static final int DEVICE_IN_FM_TUNER = AudioSystem.DEVICE_IN_FM_TUNER;
+ /** @hide
+ * The audio input device code for a TV tuner
+ */
+ public static final int DEVICE_IN_TV_TUNER = AudioSystem.DEVICE_IN_TV_TUNER;
+ /** @hide
+ * The audio input device code for an analog jack with line impedance detected
+ */
+ public static final int DEVICE_IN_LINE = AudioSystem.DEVICE_IN_LINE;
+ /** @hide
+ * The audio input device code for a S/PDIF digital connection
+ */
+ public static final int DEVICE_IN_SPDIF = AudioSystem.DEVICE_IN_SPDIF;
+
+ /**
+ * Return true if the device code corresponds to an output device.
+ * @hide
+ */
+ public static boolean isOutputDevice(int device)
+ {
+ return (device & AudioSystem.DEVICE_BIT_IN) == 0;
+ }
+
+ /**
+ * Return true if the device code corresponds to an input device.
+ * @hide
+ */
+ public static boolean isInputDevice(int device)
+ {
+ return (device & AudioSystem.DEVICE_BIT_IN) == AudioSystem.DEVICE_BIT_IN;
+ }
+
+
/**
* Return the enabled devices for the specified output stream type.
*
@@ -2635,9 +2766,17 @@
* {@link #DEVICE_OUT_BLUETOOTH_A2DP},
* {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES},
* {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER},
- * {@link #DEVICE_OUT_AUX_DIGITAL},
+ * {@link #DEVICE_OUT_HDMI},
* {@link #DEVICE_OUT_ANLG_DOCK_HEADSET},
* {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}.
+ * {@link #DEVICE_OUT_USB_ACCESSORY}.
+ * {@link #DEVICE_OUT_USB_DEVICE}.
+ * {@link #DEVICE_OUT_REMOTE_SUBMIX}.
+ * {@link #DEVICE_OUT_TELEPHONY_TX}.
+ * {@link #DEVICE_OUT_LINE}.
+ * {@link #DEVICE_OUT_HDMI_ARC}.
+ * {@link #DEVICE_OUT_SPDIF}.
+ * {@link #DEVICE_OUT_FM}.
* {@link #DEVICE_OUT_DEFAULT} is not used here.
*
* The implementation may support additional device codes beyond those listed, so
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index bb8cfa6..6e623a5 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -423,7 +423,7 @@
public final static int STREAM_REMOTE_MUSIC = -200;
// Devices for which the volume is fixed and VolumePanel slider should be disabled
- final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+ final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ALL_USB;
@@ -2895,7 +2895,7 @@
public String getSettingNameForDevice(int device) {
String name = mVolumeIndexSettingName;
- String suffix = AudioSystem.getDeviceName(device);
+ String suffix = AudioSystem.getOutputDeviceName(device);
if (suffix.isEmpty()) {
return name;
}
@@ -3935,7 +3935,7 @@
// sent if none of these devices is connected.
int mBecomingNoisyIntentDevices =
AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
- AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_AUX_DIGITAL |
+ AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ALL_USB;
@@ -3992,7 +3992,7 @@
} else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {
connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;
intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
- } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) {
+ } else if (device == AudioSystem.DEVICE_OUT_HDMI) {
connType = AudioRoutesInfo.MAIN_HDMI;
intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG);
}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 5ddb198..0c45443 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -234,11 +234,17 @@
public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;
public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;
public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
+ public static final int DEVICE_OUT_HDMI = DEVICE_OUT_AUX_DIGITAL;
public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;
+ public static final int DEVICE_OUT_TELEPHONY_TX = 0x10000;
+ public static final int DEVICE_OUT_LINE = 0x20000;
+ public static final int DEVICE_OUT_HDMI_ARC = 0x40000;
+ public static final int DEVICE_OUT_SPDIF = 0x80000;
+ public static final int DEVICE_OUT_FM = 0x100000;
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -252,12 +258,17 @@
DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
- DEVICE_OUT_AUX_DIGITAL |
+ DEVICE_OUT_HDMI |
DEVICE_OUT_ANLG_DOCK_HEADSET |
DEVICE_OUT_DGTL_DOCK_HEADSET |
DEVICE_OUT_USB_ACCESSORY |
DEVICE_OUT_USB_DEVICE |
DEVICE_OUT_REMOTE_SUBMIX |
+ DEVICE_OUT_TELEPHONY_TX |
+ DEVICE_OUT_LINE |
+ DEVICE_OUT_HDMI_ARC |
+ DEVICE_OUT_SPDIF |
+ DEVICE_OUT_FM |
DEVICE_OUT_DEFAULT);
public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -275,13 +286,20 @@
public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = DEVICE_BIT_IN | 0x8;
public static final int DEVICE_IN_WIRED_HEADSET = DEVICE_BIT_IN | 0x10;
public static final int DEVICE_IN_AUX_DIGITAL = DEVICE_BIT_IN | 0x20;
+ public static final int DEVICE_IN_HDMI = DEVICE_IN_AUX_DIGITAL;
public static final int DEVICE_IN_VOICE_CALL = DEVICE_BIT_IN | 0x40;
+ public static final int DEVICE_IN_TELEPHONY_RX = DEVICE_IN_VOICE_CALL;
public static final int DEVICE_IN_BACK_MIC = DEVICE_BIT_IN | 0x80;
public static final int DEVICE_IN_REMOTE_SUBMIX = DEVICE_BIT_IN | 0x100;
public static final int DEVICE_IN_ANLG_DOCK_HEADSET = DEVICE_BIT_IN | 0x200;
public static final int DEVICE_IN_DGTL_DOCK_HEADSET = DEVICE_BIT_IN | 0x400;
public static final int DEVICE_IN_USB_ACCESSORY = DEVICE_BIT_IN | 0x800;
public static final int DEVICE_IN_USB_DEVICE = DEVICE_BIT_IN | 0x1000;
+ public static final int DEVICE_IN_FM_TUNER = DEVICE_BIT_IN | 0x2000;
+ public static final int DEVICE_IN_TV_TUNER = DEVICE_BIT_IN | 0x4000;
+ public static final int DEVICE_IN_LINE = DEVICE_BIT_IN | 0x8000;
+ public static final int DEVICE_IN_SPDIF = DEVICE_BIT_IN | 0x10000;
+
public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION |
@@ -289,14 +307,18 @@
DEVICE_IN_BUILTIN_MIC |
DEVICE_IN_BLUETOOTH_SCO_HEADSET |
DEVICE_IN_WIRED_HEADSET |
- DEVICE_IN_AUX_DIGITAL |
- DEVICE_IN_VOICE_CALL |
+ DEVICE_IN_HDMI |
+ DEVICE_IN_TELEPHONY_RX |
DEVICE_IN_BACK_MIC |
DEVICE_IN_REMOTE_SUBMIX |
DEVICE_IN_ANLG_DOCK_HEADSET |
DEVICE_IN_DGTL_DOCK_HEADSET |
DEVICE_IN_USB_ACCESSORY |
DEVICE_IN_USB_DEVICE |
+ DEVICE_IN_FM_TUNER |
+ DEVICE_IN_TV_TUNER |
+ DEVICE_IN_LINE |
+ DEVICE_IN_SPDIF |
DEVICE_IN_DEFAULT);
public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
@@ -318,13 +340,19 @@
public static final String DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME = "bt_a2dp_hp";
public static final String DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME = "bt_a2dp_spk";
public static final String DEVICE_OUT_AUX_DIGITAL_NAME = "aux_digital";
+ public static final String DEVICE_OUT_HDMI_NAME = "hdmi";
public static final String DEVICE_OUT_ANLG_DOCK_HEADSET_NAME = "analog_dock";
public static final String DEVICE_OUT_DGTL_DOCK_HEADSET_NAME = "digital_dock";
public static final String DEVICE_OUT_USB_ACCESSORY_NAME = "usb_accessory";
public static final String DEVICE_OUT_USB_DEVICE_NAME = "usb_device";
public static final String DEVICE_OUT_REMOTE_SUBMIX_NAME = "remote_submix";
+ public static final String DEVICE_OUT_TELEPHONY_TX_NAME = "telephony_tx";
+ public static final String DEVICE_OUT_LINE_NAME = "line";
+ public static final String DEVICE_OUT_HDMI_ARC_NAME = "hmdi_arc";
+ public static final String DEVICE_OUT_SPDIF_NAME = "spdif";
+ public static final String DEVICE_OUT_FM_NAME = "fm_transmitter";
- public static String getDeviceName(int device)
+ public static String getOutputDeviceName(int device)
{
switch(device) {
case DEVICE_OUT_EARPIECE:
@@ -347,8 +375,8 @@
return DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES_NAME;
case DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
return DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER_NAME;
- case DEVICE_OUT_AUX_DIGITAL:
- return DEVICE_OUT_AUX_DIGITAL_NAME;
+ case DEVICE_OUT_HDMI:
+ return DEVICE_OUT_HDMI_NAME;
case DEVICE_OUT_ANLG_DOCK_HEADSET:
return DEVICE_OUT_ANLG_DOCK_HEADSET_NAME;
case DEVICE_OUT_DGTL_DOCK_HEADSET:
@@ -359,12 +387,23 @@
return DEVICE_OUT_USB_DEVICE_NAME;
case DEVICE_OUT_REMOTE_SUBMIX:
return DEVICE_OUT_REMOTE_SUBMIX_NAME;
+ case DEVICE_OUT_TELEPHONY_TX:
+ return DEVICE_OUT_TELEPHONY_TX_NAME;
+ case DEVICE_OUT_LINE:
+ return DEVICE_OUT_LINE_NAME;
+ case DEVICE_OUT_HDMI_ARC:
+ return DEVICE_OUT_HDMI_ARC_NAME;
+ case DEVICE_OUT_SPDIF:
+ return DEVICE_OUT_SPDIF_NAME;
+ case DEVICE_OUT_FM:
+ return DEVICE_OUT_FM_NAME;
case DEVICE_OUT_DEFAULT:
default:
return "";
}
}
+
// phone state, match audio_mode???
public static final int PHONE_STATE_OFFCALL = 0;
public static final int PHONE_STATE_RINGING = 1;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 37f45c2..26ae3cc 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -407,6 +407,19 @@
}
/**
+ * Get a {@link MediaSession} associated with this RCC. It will only have a
+ * session while it is registered with
+ * {@link AudioManager#registerRemoteControlClient}. The session returned
+ * should not be modified directly by the application but may be used with
+ * other APIs that require a session.
+ *
+ * @return A media session object or null.
+ */
+ public MediaSession getMediaSession() {
+ return mSession;
+ }
+
+ /**
* Class used to modify metadata in a {@link RemoteControlClient} object.
* Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor,
* on which you set the metadata for the RemoteControlClient instance. Once all the information
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index a68ad2f..97051ff 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -22,21 +22,6 @@
android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <com.android.systemui.recents.views.TaskInfoView
- android:id="@+id/task_view_info_pane"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="invisible"
- android:background="@color/recents_task_bar_default_background_color">
- <Button
- android:id="@+id/task_view_app_info_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="20dp"
- android:layout_marginEnd="20dp"
- android:layout_gravity="top|center_horizontal"
- android:text="@string/recents_app_info_button_label" />
- </com.android.systemui.recents.views.TaskInfoView>
<com.android.systemui.recents.views.TaskBarView
android:id="@+id/task_view_bar"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 79545b3..fcbd0f4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -31,8 +31,6 @@
public static final boolean EnableTaskStackClipping = false;
// Enables the use of theme colors as the task bar background
public static final boolean EnableTaskBarThemeColors = true;
- // Enables the info pane on long-pressing the task
- public static final boolean EnableInfoPane = false;
// Enables app-info pane on long-pressing the icon
public static final boolean EnableDevAppInfoOnLongPress = true;
// Enables the search bar layout
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index bae8a99..de696db 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -394,16 +394,9 @@
public void onBackPressed() {
boolean interceptedByInfoPanelClose = false;
- // Try and return from any open info panes
- if (Constants.DebugFlags.App.EnableInfoPane) {
- interceptedByInfoPanelClose = mRecentsView.closeOpenInfoPanes();
- }
-
- // If we haven't been intercepted already, then unfilter any stacks
- if (!interceptedByInfoPanelClose) {
- if (!mRecentsView.unfilterFilteredStacks()) {
- super.onBackPressed();
- }
+ // Unfilter any stacks
+ if (!mRecentsView.unfilterFilteredStacks()) {
+ super.onBackPressed();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index c63e688..cad54fa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -301,24 +301,6 @@
return insets.consumeSystemWindowInsets(false, false, false, true);
}
- /** Closes any open info panes */
- public boolean closeOpenInfoPanes() {
- if (mBSP != null) {
- // Get the first stack view
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child instanceof TaskStackView) {
- TaskStackView stackView = (TaskStackView) child;
- if (stackView.closeOpenInfoPanes()) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
/** Unfilters any filtered stacks */
public boolean unfilterFilteredStacks() {
if (mBSP != null) {
@@ -346,9 +328,6 @@
mCb.onTaskLaunching();
}
- // Close any open info panes
- closeOpenInfoPanes();
-
final Runnable launchRunnable = new Runnable() {
@Override
public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
deleted file mode 100644
index 7b6572b..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Path;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.RippleDrawable;
-import android.util.AttributeSet;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.Utilities;
-import com.android.systemui.recents.model.Task;
-
-
-/* The task info view */
-class TaskInfoView extends FrameLayout {
-
- Button mAppInfoButton;
-
- // Circular clip animation
- boolean mCircularClipEnabled;
- Path mClipPath = new Path();
- float mClipRadius;
- float mMaxClipRadius;
- Point mClipOrigin = new Point();
- ObjectAnimator mCircularClipAnimator;
-
- public TaskInfoView(Context context) {
- this(context, null);
- }
-
- public TaskInfoView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- @Override
- protected void onFinishInflate() {
- // Initialize the buttons on the info panel
- mAppInfoButton = (Button) findViewById(R.id.task_view_app_info_button);
- }
-
- /** Updates the positions of each of the items to fit in the rect specified */
- void updateContents(Rect visibleRect) {
- // Offset the app info button
- mAppInfoButton.setTranslationY(visibleRect.top +
- (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2);
- }
-
- /** Sets the circular clip radius on this panel */
- public void setCircularClipRadius(float r) {
- mClipRadius = r;
- invalidate();
- }
-
- /** Gets the circular clip radius on this panel */
- public float getCircularClipRadius() {
- return mClipRadius;
- }
-
- /** Animates the circular clip radius on the icon */
- void animateCircularClip(Point o, float fromRadius, float toRadius,
- final Runnable postRunnable, boolean animateInContent) {
- if (mCircularClipAnimator != null) {
- mCircularClipAnimator.cancel();
- }
-
- // Calculate the max clip radius to each of the corners
- int w = getMeasuredWidth() - o.x;
- int h = getMeasuredHeight() - o.y;
- // origin to tl, tr, br, bl
- mMaxClipRadius = (int) Math.ceil(Math.sqrt(o.x * o.x + o.y * o.y));
- mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + o.y * o.y)));
- mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + h * h)));
- mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(o.x * o.x + h * h)));
-
- mClipOrigin.set(o.x, o.y);
- mClipRadius = fromRadius;
- int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
- mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
- mCircularClipAnimator.setDuration(duration);
- mCircularClipAnimator.setInterpolator(
- RecentsConfiguration.getInstance().defaultBezierInterpolator);
- mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mCircularClipEnabled = false;
- if (postRunnable != null) {
- postRunnable.run();
- }
- }
- });
- mCircularClipAnimator.start();
- mCircularClipEnabled = true;
-
- if (animateInContent) {
- animateAppInfoButtonIn(duration);
- }
- }
-
- /** Cancels the circular clip animation. */
- void cancelCircularClipAnimation() {
- if (mCircularClipAnimator != null) {
- mCircularClipAnimator.cancel();
- }
- }
-
- void animateAppInfoButtonIn(int duration) {
- mAppInfoButton.setScaleX(0.75f);
- mAppInfoButton.setScaleY(0.75f);
- mAppInfoButton.animate()
- .scaleX(1f)
- .scaleY(1f)
- .setDuration(duration)
- .setInterpolator(RecentsConfiguration.getInstance().defaultBezierInterpolator)
- .withLayer()
- .start();
- }
-
- /** Binds the info view to the task */
- void rebindToTask(Task t, boolean animate) {
- RecentsConfiguration configuration = RecentsConfiguration.getInstance();
- if (Constants.DebugFlags.App.EnableTaskBarThemeColors && t.colorPrimary != 0) {
- setBackgroundColor(t.colorPrimary);
- // Workaround: The button currently doesn't support setting a custom background tint
- // not defined in the theme. Just lower the alpha on the button to make it blend more
- // into the background.
- if (mAppInfoButton.getBackground() instanceof RippleDrawable) {
- RippleDrawable d = (RippleDrawable) mAppInfoButton.getBackground();
- if (d != null) {
- d.setAlpha(96);
- }
- }
- } else {
- setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- int saveCount = 0;
- if (mCircularClipEnabled) {
- saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
- mClipPath.reset();
- mClipPath.addCircle(mClipOrigin.x, mClipOrigin.y, mClipRadius * mMaxClipRadius,
- Path.Direction.CW);
- canvas.clipPath(mClipPath);
- }
- super.draw(canvas);
- if (mCircularClipEnabled) {
- canvas.restoreToCount(saveCount);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 37c3c35..0687222 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -54,7 +54,7 @@
/* The visual representation of a task stack view */
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
- View.OnClickListener, View.OnLongClickListener, RecentsPackageMonitor.PackageCallbacks {
+ View.OnClickListener, RecentsPackageMonitor.PackageCallbacks {
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
@@ -79,7 +79,6 @@
int mMinScroll;
int mMaxScroll;
int mStashedScroll;
- int mLastInfoPaneStackScroll;
int mFocusedTaskIndex = -1;
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
@@ -290,17 +289,6 @@
public void setStackScroll(int value) {
mStackScroll = value;
requestSynchronizeStackViewsWithModel();
-
- // Close any open info panes if the user has scrolled away from them
- boolean isAnimatingScroll = (mScrollAnimator != null && mScrollAnimator.isRunning());
- if (mLastInfoPaneStackScroll > -1 && !isAnimatingScroll) {
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- if (Math.abs(mStackScroll - mLastInfoPaneStackScroll) >
- config.taskStackScrollDismissInfoPaneDistance) {
- // Close any open info panes
- closeOpenInfoPanes();
- }
- }
}
/** Sets the current stack scroll without synchronizing the stack view with the model */
public void setStackScrollRaw(int value) {
@@ -455,21 +443,6 @@
}
}
- /** Closes any open info panes. */
- boolean closeOpenInfoPanes() {
- if (!Constants.DebugFlags.App.EnableInfoPane) return false;
-
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- if (tv.isInfoPaneVisible()) {
- tv.hideInfoPane();
- return true;
- }
- }
- return false;
- }
-
/** Focuses the task at the specified index in the stack */
void focusTask(int taskIndex, boolean scrollToNewPosition) {
Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "" + taskIndex);
@@ -949,9 +922,6 @@
@Override
public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
Task filteredTask) {
- // Close any open info panes
- closeOpenInfoPanes();
-
// Stash the scroll and filtered task for us to restore to when we unfilter
mStashedScroll = getStackScroll();
@@ -976,9 +946,6 @@
@Override
public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
- // Close any open info panes
- closeOpenInfoPanes();
-
// Calculate the current task transforms
final ArrayList<TaskViewTransform> curTaskTransforms =
getStackTransforms(curTasks, getStackScroll(), null, true);
@@ -1058,9 +1025,6 @@
// Set the callbacks and listeners for this new view
tv.setOnClickListener(this);
- if (Constants.DebugFlags.App.EnableInfoPane) {
- tv.setOnLongClickListener(this);
- }
tv.setCallbacks(this);
} else {
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
@@ -1094,17 +1058,6 @@
}
@Override
- public void onTaskInfoPanelShown(TaskView tv) {
- // Do nothing
- }
-
- @Override
- public void onTaskInfoPanelHidden(TaskView tv) {
- // Unset the saved scroll
- mLastInfoPaneStackScroll = -1;
- }
-
- @Override
public void onTaskAppInfoClicked(TaskView tv) {
if (mCb != null) {
mCb.onTaskAppInfoLaunched(tv.getTask());
@@ -1129,52 +1082,11 @@
Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
task + " cb: " + mCb);
- // Close any open info panes if the user taps on another task
- if (closeOpenInfoPanes()) {
- return;
- }
-
if (mCb != null) {
mCb.onTaskLaunched(this, tv, mStack, task);
}
}
- @Override
- public boolean onLongClick(View v) {
- if (!Constants.DebugFlags.App.EnableInfoPane) return false;
-
- TaskView tv = (TaskView) v;
-
- // Close any other task info panels if we launch another info pane
- closeOpenInfoPanes();
-
- // Scroll the task view so that it is maximally visible
- float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
- int taskIndex = mStack.indexOfTask(tv.getTask());
- int curScroll = getStackScroll();
- int newScroll = (int) Math.max(mMinScroll, Math.min(mMaxScroll, taskIndex * overlapHeight));
- TaskViewTransform transform = getStackTransform(taskIndex, curScroll);
- Rect nonOverlapRect = new Rect(transform.rect);
- if (taskIndex < (mStack.getTaskCount() - 1)) {
- nonOverlapRect.bottom = nonOverlapRect.top + (int) overlapHeight;
- }
-
- // XXX: Use HW Layers
- if (transform.t < 0f) {
- animateScroll(curScroll, newScroll, null);
- } else if (nonOverlapRect.bottom > mStackRectSansPeek.bottom) {
- // Check if we are out of bounds, if so, just scroll it in such that the bottom of the
- // task view is visible
- newScroll = curScroll - (mStackRectSansPeek.bottom - nonOverlapRect.bottom);
- animateScroll(curScroll, newScroll, null);
- }
- mLastInfoPaneStackScroll = newScroll;
-
- // Show the info pane for this task view
- tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
- return true;
- }
-
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
@@ -1550,13 +1462,6 @@
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- // If the info panel is currently showing on this view, then we need to dismiss it
- if (Constants.DebugFlags.App.EnableInfoPane) {
- TaskView tv = (TaskView) v;
- if (tv.isInfoPaneVisible()) {
- tv.hideInfoPane();
- }
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 46af4c1..780f274 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -44,8 +44,6 @@
/** The TaskView callbacks */
interface TaskViewCallbacks {
public void onTaskIconClicked(TaskView tv);
- public void onTaskInfoPanelShown(TaskView tv);
- public void onTaskInfoPanelHidden(TaskView tv);
public void onTaskAppInfoClicked(TaskView tv);
public void onTaskDismissed(TaskView tv);
@@ -58,14 +56,12 @@
Task mTask;
boolean mTaskDataLoaded;
- boolean mTaskInfoPaneVisible;
boolean mIsFocused;
Point mLastTouchDown = new Point();
Path mRoundedRectClipPath = new Path();
TaskThumbnailView mThumbnailView;
TaskBarView mBarView;
- TaskInfoView mInfoView;
TaskViewCallbacks mCb;
@@ -94,7 +90,6 @@
// Bind the views
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
- mInfoView = (TaskInfoView) findViewById(R.id.task_view_info_pane);
if (mTaskDataLoaded) {
onTaskDataLoaded(false);
@@ -280,63 +275,6 @@
return outRect;
}
- /** Returns whether this task has an info pane visible */
- boolean isInfoPaneVisible() {
- return mTaskInfoPaneVisible;
- }
-
- /** Shows the info pane if it is not visible. */
- void showInfoPane(Rect taskVisibleRect) {
- if (mTaskInfoPaneVisible) return;
-
- // Remove the bar view from the visible rect and update the info pane contents
- taskVisibleRect.top += mBarView.getMeasuredHeight();
- mInfoView.updateContents(taskVisibleRect);
-
- // Show the info pane and animate it into view
- mInfoView.setVisibility(View.VISIBLE);
- mInfoView.animateCircularClip(mLastTouchDown, 0f, 1f, null, true);
- mInfoView.setOnClickListener(this);
- mTaskInfoPaneVisible = true;
-
- // Notify any callbacks
- if (mCb != null) {
- mCb.onTaskInfoPanelShown(this);
- }
- }
-
- /** Hides the info pane if it is visible. */
- void hideInfoPane() {
- if (!mTaskInfoPaneVisible) return;
- RecentsConfiguration config = RecentsConfiguration.getInstance();
-
- // Cancel any circular clip animation
- mInfoView.cancelCircularClipAnimation();
-
- // Animate the info pane out
- mInfoView.animate()
- .alpha(0f)
- .setDuration(config.taskViewInfoPaneAnimDuration)
- .setInterpolator(config.defaultBezierInterpolator)
- .withLayer()
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mInfoView.setVisibility(View.INVISIBLE);
- mInfoView.setOnClickListener(null);
-
- mInfoView.setAlpha(1f);
- }
- })
- .start();
- mTaskInfoPaneVisible = false;
-
- // Notify any callbacks
- if (mCb != null) {
- mCb.onTaskInfoPanelHidden(this);
- }
- }
-
/** Enable the hw layers on this task view */
void enableHwLayers() {
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -408,11 +346,10 @@
@Override
public void onTaskDataLoaded(boolean reloadingTaskData) {
- if (mThumbnailView != null && mBarView != null && mInfoView != null) {
+ if (mThumbnailView != null && mBarView != null) {
// Bind each of the views to the new task data
mThumbnailView.rebindToTask(mTask, reloadingTaskData);
mBarView.rebindToTask(mTask, reloadingTaskData);
- mInfoView.rebindToTask(mTask, reloadingTaskData);
// Rebind any listeners
mBarView.mApplicationIcon.setOnClickListener(this);
mBarView.mDismissButton.setOnClickListener(this);
@@ -424,16 +361,13 @@
mBarView.mApplicationIcon.setOnLongClickListener(this);
}
}
- if (Constants.DebugFlags.App.EnableInfoPane) {
- mInfoView.mAppInfoButton.setOnClickListener(this);
- }
}
mTaskDataLoaded = true;
}
@Override
public void onTaskDataUnloaded() {
- if (mThumbnailView != null && mBarView != null && mInfoView != null) {
+ if (mThumbnailView != null && mBarView != null) {
// Unbind each of the views from the task data and remove the task callback
mTask.setCallbacks(null);
mThumbnailView.unbindFromTask();
@@ -444,18 +378,13 @@
if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
mBarView.mApplicationIcon.setOnLongClickListener(null);
}
- if (Constants.DebugFlags.App.EnableInfoPane) {
- mInfoView.mAppInfoButton.setOnClickListener(null);
- }
}
mTaskDataLoaded = false;
}
@Override
public void onClick(View v) {
- if (v == mInfoView) {
- hideInfoPane();
- } else if (v == mBarView.mApplicationIcon) {
+ if (v == mBarView.mApplicationIcon) {
mCb.onTaskIconClicked(this);
} else if (v == mBarView.mDismissButton) {
// Animate out the view and call the callback
@@ -466,8 +395,6 @@
mCb.onTaskDismissed(tv);
}
});
- } else if (v == mInfoView.mAppInfoButton) {
- mCb.onTaskAppInfoClicked(this);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 724b6a4..ac16164 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -89,7 +89,7 @@
super.onFinishInflate();
mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
- updateBackgroundResource();
+ updateBackgroundResources();
}
private final Runnable mTapTimeoutRunnable = new Runnable() {
@@ -215,9 +215,9 @@
if (mDimmed != dimmed) {
mDimmed = dimmed;
if (fade) {
- fadeBackgroundResource();
+ fadeBackground();
} else {
- updateBackgroundResource();
+ updateBackground();
}
}
}
@@ -233,14 +233,14 @@
mBgTint = bgTint;
mDimmedBgResId = dimmedBgResId;
mDimmedBgTint = dimmedTint;
- updateBackgroundResource();
+ updateBackgroundResources();
}
public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
setBackgroundResourceIds(bgResId, 0, dimmedBgResId, 0);
}
- private void fadeBackgroundResource() {
+ private void fadeBackground() {
if (mDimmed) {
mBackgroundDimmed.setVisibility(View.VISIBLE);
} else {
@@ -256,7 +256,7 @@
mBackgroundAnimator.removeAllListeners();
mBackgroundAnimator.cancel();
if (duration <= 0) {
- updateBackgroundResource();
+ updateBackground();
return;
}
}
@@ -279,19 +279,22 @@
mBackgroundAnimator.start();
}
- private void updateBackgroundResource() {
+ private void updateBackground() {
if (mDimmed) {
mBackgroundDimmed.setVisibility(View.VISIBLE);
- mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint);
mBackgroundNormal.setVisibility(View.INVISIBLE);
} else {
mBackgroundDimmed.setVisibility(View.INVISIBLE);
mBackgroundNormal.setVisibility(View.VISIBLE);
- mBackgroundNormal.setCustomBackground(mBgResId, mBgTint);
mBackgroundNormal.setAlpha(1f);
}
}
+ private void updateBackgroundResources() {
+ mBackgroundDimmed.setCustomBackground(mDimmedBgResId, mDimmedBgTint);
+ mBackgroundNormal.setCustomBackground(mBgResId, mBgTint);
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index eb4e77a..e699dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -619,7 +619,6 @@
protected void hideRecents(boolean triggeredFromAltTab) {
if (mRecents != null) {
- sendCloseSystemWindows(mContext, SYSTEM_DIALOG_REASON_RECENT_APPS);
mRecents.hideRecents(triggeredFromAltTab);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 0d3116f..eaaac10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -90,9 +90,8 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!mActualHeightInitialized && mActualHeight == 0) {
- mActualHeight = getInitialHeight();
+ setActualHeight(getInitialHeight());
}
- mActualHeightInitialized = true;
}
protected int getInitialHeight() {
@@ -127,6 +126,7 @@
}
public void setActualHeight(int actualHeight) {
+ mActualHeightInitialized = true;
setActualHeight(actualHeight, true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index e49ec64..3c080fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -31,7 +31,6 @@
private Drawable mBackground;
private int mClipTopAmount;
private int mActualHeight;
- private boolean mActualHeightInitialized;
public NotificationBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -39,15 +38,6 @@
}
@Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (!mActualHeightInitialized && mActualHeight == 0) {
- mActualHeight = getHeight();
- }
- mActualHeightInitialized = true;
- }
-
- @Override
protected void onDraw(Canvas canvas) {
draw(canvas, mBackground);
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 168742f..4ab8a01 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -22,7 +22,6 @@
import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -40,7 +39,6 @@
import android.os.WorkSource;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -104,13 +102,21 @@
int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
boolean mLastWakeLockUnimportantForLogging;
+ ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<Alarm>();
ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
final AlarmHandler mHandler = new AlarmHandler();
ClockReceiver mClockReceiver;
+ InteractiveStateReceiver mInteractiveStateReceiver;
private UninstallReceiver mUninstallReceiver;
final ResultReceiver mResultReceiver = new ResultReceiver();
PendingIntent mTimeTickSender;
PendingIntent mDateChangeSender;
+ boolean mInteractive = true;
+ long mNonInteractiveStartTime;
+ long mNonInteractiveTime;
+ long mLastAlarmDeliveryTime;
+ long mStartCurrentDelayTime;
+ long mNextNonWakeupDeliveryTime;
class WakeupEvent {
public long when;
@@ -318,7 +324,11 @@
final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
@Override
public int compare(Alarm lhs, Alarm rhs) {
- if (lhs.wakeup != rhs.wakeup) {
+ if ((!lhs.operation.getCreatorPackage().equals(rhs.operation.getCreatorPackage()))
+ && lhs.wakeup != rhs.wakeup) {
+ // We want to put wakeup alarms before non-wakeup alarms, since they are
+ // the things that drive most activity in the alarm manager. However,
+ // alarms from the same package should always be ordered strictly by time.
return lhs.wakeup ? -1 : 1;
}
if (lhs.whenElapsed < rhs.whenElapsed) {
@@ -424,24 +434,21 @@
static final class InFlight extends Intent {
final PendingIntent mPendingIntent;
final WorkSource mWorkSource;
- final Pair<String, ComponentName> mTarget;
+ final String mTag;
final BroadcastStats mBroadcastStats;
final FilterStats mFilterStats;
final int mAlarmType;
InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
- int alarmType) {
+ int alarmType, String tag) {
mPendingIntent = pendingIntent;
mWorkSource = workSource;
- Intent intent = pendingIntent.getIntent();
- mTarget = intent != null
- ? new Pair<String, ComponentName>(intent.getAction(), intent.getComponent())
- : null;
+ mTag = tag;
mBroadcastStats = service.getStatsLocked(pendingIntent);
- FilterStats fs = mBroadcastStats.filterStats.get(mTarget);
+ FilterStats fs = mBroadcastStats.filterStats.get(mTag);
if (fs == null) {
- fs = new FilterStats(mBroadcastStats, mTarget);
- mBroadcastStats.filterStats.put(mTarget, fs);
+ fs = new FilterStats(mBroadcastStats, mTag);
+ mBroadcastStats.filterStats.put(mTag, fs);
}
mFilterStats = fs;
mAlarmType = alarmType;
@@ -450,7 +457,7 @@
static final class FilterStats {
final BroadcastStats mBroadcastStats;
- final Pair<String, ComponentName> mTarget;
+ final String mTag;
long aggregateTime;
int count;
@@ -458,9 +465,9 @@
long startTime;
int nesting;
- FilterStats(BroadcastStats broadcastStats, Pair<String, ComponentName> target) {
+ FilterStats(BroadcastStats broadcastStats, String tag) {
mBroadcastStats = broadcastStats;
- mTarget = target;
+ mTag = tag;
}
}
@@ -473,8 +480,7 @@
int numWakeup;
long startTime;
int nesting;
- final ArrayMap<Pair<String, ComponentName>, FilterStats> filterStats
- = new ArrayMap<Pair<String, ComponentName>, FilterStats>();
+ final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
BroadcastStats(int uid, String packageName) {
mUid = uid;
@@ -484,7 +490,11 @@
final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
= new SparseArray<ArrayMap<String, BroadcastStats>>();
-
+
+ int mNumDelayedAlarms = 0;
+ long mTotalDelayTime = 0;
+ long mMaxDelayTime = 0;
+
@Override
public void onStart() {
mNativeData = init();
@@ -511,6 +521,7 @@
mClockReceiver = new ClockReceiver();
mClockReceiver.scheduleTimeTickEvent();
mClockReceiver.scheduleDateChangedEvent();
+ mInteractiveStateReceiver = new InteractiveStateReceiver();
mUninstallReceiver = new UninstallReceiver();
if (mNativeData != 0) {
@@ -735,13 +746,29 @@
pw.print("nowRTC="); pw.print(nowRTC);
pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
- pw.print(" nowELAPSED="); pw.println(nowELAPSED);
+ pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
+ pw.println();
+ if (!mInteractive) {
+ pw.print("Time since non-interactive: ");
+ TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
+ pw.println();
+ pw.print("Max wakeup delay: ");
+ TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
+ pw.println();
+ pw.print("Time since last dispatch: ");
+ TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
+ pw.println();
+ pw.print("Next non-wakeup delivery time: ");
+ TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
+ pw.println();
+ }
long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
- pw.print("Next alarm: "); pw.print(mNextNonWakeup);
+ pw.print("Next non-wakeup alarm: ");
+ TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
- pw.print("Next wakeup: "); pw.print(mNextWakeup);
+ pw.print("Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
if (mAlarmBatches.size() > 0) {
@@ -750,11 +777,27 @@
pw.println(mAlarmBatches.size());
for (Batch b : mAlarmBatches) {
pw.print(b); pw.println(':');
- dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC);
+ dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
}
}
pw.println();
+ pw.print("Past-due non-wakeup alarms: ");
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ pw.println(mPendingNonWakeupAlarms.size());
+ dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
+ } else {
+ pw.println("(none)");
+ }
+ pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
+ pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
+ pw.println();
+ pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
+ pw.print(", max non-interactive time: ");
+ TimeUtils.formatDuration(mNonInteractiveTime, pw);
+ pw.println();
+
+ pw.println();
pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
pw.println();
@@ -811,13 +854,7 @@
pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
pw.println();
- pw.print(" ");
- if (fs.mTarget.first != null) {
- pw.print(" act="); pw.print(fs.mTarget.first);
- }
- if (fs.mTarget.second != null) {
- pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
- }
+ pw.print(" "); pw.print(fs.mTag);
pw.println();
}
}
@@ -849,13 +886,8 @@
TimeUtils.formatDuration(fs.aggregateTime, pw);
pw.print(" "); pw.print(fs.numWakeup);
pw.print(" wakes " ); pw.print(fs.count);
- pw.print(" alarms:");
- if (fs.mTarget.first != null) {
- pw.print(" act="); pw.print(fs.mTarget.first);
- }
- if (fs.mTarget.second != null) {
- pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
- }
+ pw.print(" alarms: ");
+ pw.print(fs.mTag);
pw.println();
}
}
@@ -883,7 +915,7 @@
}
}
- private void logBatchesLocked() {
+ private void logBatchesLocked(SimpleDateFormat sdf) {
ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
PrintWriter pw = new PrintWriter(bs);
final long nowRTC = System.currentTimeMillis();
@@ -892,7 +924,7 @@
for (int iz = 0; iz < NZ; iz++) {
Batch bz = mAlarmBatches.get(iz);
pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
- dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC);
+ dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
pw.flush();
Slog.v(TAG, bs.toString());
bs.reset();
@@ -910,7 +942,8 @@
lastTime = b.start;
} else {
Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
- logBatchesLocked();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ logBatchesLocked(sdf);
return false;
}
}
@@ -932,6 +965,7 @@
void rescheduleKernelAlarmsLocked() {
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
// prior to that which contains no wakeups, we schedule that as well.
+ long nextNonWakeup = 0;
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
final Batch firstBatch = mAlarmBatches.get(0);
@@ -939,11 +973,19 @@
mNextWakeup = firstWakeup.start;
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
}
- if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
- mNextNonWakeup = firstBatch.start;
- setLocked(ELAPSED_REALTIME, firstBatch.start);
+ if (firstBatch != firstWakeup) {
+ nextNonWakeup = firstBatch.start;
}
}
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
+ nextNonWakeup = mNextNonWakeupDeliveryTime;
+ }
+ }
+ if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
+ mNextNonWakeup = nextNonWakeup;
+ setLocked(ELAPSED_REALTIME, nextNonWakeup);
+ }
}
private void removeLocked(PendingIntent operation) {
@@ -1003,6 +1045,32 @@
}
}
+ void interactiveStateChangedLocked(boolean interactive) {
+ if (mInteractive != interactive) {
+ mInteractive = interactive;
+ final long nowELAPSED = SystemClock.elapsedRealtime();
+ if (interactive) {
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+ mTotalDelayTime += thisDelayTime;
+ if (mMaxDelayTime < thisDelayTime) {
+ mMaxDelayTime = thisDelayTime;
+ }
+ deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
+ mPendingNonWakeupAlarms.clear();
+ }
+ if (mNonInteractiveStartTime > 0) {
+ long dur = nowELAPSED - mNonInteractiveStartTime;
+ if (dur > mNonInteractiveTime) {
+ mNonInteractiveTime = dur;
+ }
+ }
+ } else {
+ mNonInteractiveStartTime = nowELAPSED;
+ }
+ }
+ }
+
boolean lookForPackageLocked(String packageName) {
for (int i = 0; i < mAlarmBatches.size(); i++) {
Batch b = mAlarmBatches.get(i);
@@ -1037,12 +1105,12 @@
}
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
- String prefix, String label, long now) {
+ String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
for (int i=list.size()-1; i>=0; i--) {
Alarm a = list.get(i);
pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
pw.print(": "); pw.println(a);
- a.dump(pw, prefix + " ", now);
+ a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
}
}
@@ -1059,14 +1127,13 @@
}
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
- String prefix, long nowELAPSED, long nowRTC) {
+ String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
for (int i=list.size()-1; i>=0; i--) {
Alarm a = list.get(i);
final String label = labelForType(a.type);
- long now = (a.type <= RTC) ? nowRTC : nowELAPSED;
pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
pw.print(": "); pw.println(a);
- a.dump(pw, prefix + " ", now);
+ a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
}
}
@@ -1077,8 +1144,9 @@
private native int setKernelTime(long nativeData, long millis);
private native int setKernelTimezone(long nativeData, int minuteswest);
- void triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
+ boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
final long nowRTC) {
+ boolean hasWakeup = false;
// batches are temporally sorted, so we need only pull from the
// start of the list until we either empty it or hit a batch
// that is not yet deliverable
@@ -1113,8 +1181,14 @@
maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
alarm.repeatInterval, alarm.operation, batch.standalone, true,
alarm.workSource);
- }
+ // For now we count this as a wakeup alarm, meaning it needs to be
+ // delivered immediately. In the future we should change this, but
+ // that required delaying when we reschedule the repeat...!
+ hasWakeup = false;
+ } else if (alarm.wakeup) {
+ hasWakeup = true;
+ }
}
}
@@ -1125,6 +1199,8 @@
Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
}
}
+
+ return hasWakeup;
}
/**
@@ -1147,15 +1223,16 @@
private static class Alarm {
public final int type;
public final boolean wakeup;
+ public final PendingIntent operation;
+ public final String tag;
+ public final WorkSource workSource;
public int count;
public long when;
public long windowLength;
public long whenElapsed; // 'when' in the elapsed time base
public long maxWhen; // also in the elapsed time base
public long repeatInterval;
- public PendingIntent operation;
- public WorkSource workSource;
-
+
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws) {
type = _type;
@@ -1167,12 +1244,17 @@
maxWhen = _maxWhen;
repeatInterval = _interval;
operation = _op;
+ tag = makeTag(_op, _type);
workSource = _ws;
}
+ public static String makeTag(PendingIntent pi, int type) {
+ return pi.getTag(type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
+ ? "*walarm*:" : "*alarm*:");
+ }
+
@Override
- public String toString()
- {
+ public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("Alarm{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
@@ -1186,11 +1268,20 @@
return sb.toString();
}
- public void dump(PrintWriter pw, String prefix, long now) {
+ public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
+ SimpleDateFormat sdf) {
+ final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
+ pw.print(prefix); pw.print("tag="); pw.println(tag);
pw.print(prefix); pw.print("type="); pw.print(type);
- pw.print(" whenElapsed="); pw.print(whenElapsed);
- pw.print(" when="); TimeUtils.formatDuration(when, now, pw);
- pw.print(" window="); pw.print(windowLength);
+ pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
+ nowELAPSED, pw);
+ if (isRtc) {
+ pw.print(" when="); pw.print(sdf.format(new Date(when)));
+ } else {
+ pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw);
+ }
+ pw.println();
+ pw.print(prefix); pw.print("window="); pw.print(windowLength);
pw.print(" repeatInterval="); pw.print(repeatInterval);
pw.print(" count="); pw.println(count);
pw.print(prefix); pw.print("operation="); pw.println(operation);
@@ -1216,6 +1307,102 @@
}
}
+ long currentNonWakeupFuzzLocked(long nowELAPSED) {
+ long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
+ if (timeSinceOn < 5*60*1000) {
+ // If the screen has been off for 5 minutes, only delay by at most two minutes.
+ return 2*60*1000;
+ } else if (timeSinceOn < 30*60*1000) {
+ // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
+ return 15*60*1000;
+ } else {
+ // Otherwise, we will delay by at most an hour.
+ return 60*60*1000;
+ }
+ }
+
+ boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
+ if (mInteractive) {
+ return false;
+ }
+ if (mLastAlarmDeliveryTime <= 0) {
+ return false;
+ }
+ if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime > nowELAPSED) {
+ // This is just a little paranoia, if somehow we have pending non-wakeup alarms
+ // and the next delivery time is in the past, then just deliver them all. This
+ // avoids bugs where we get stuck in a loop trying to poll for alarms.
+ return false;
+ }
+ long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
+ return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
+ }
+
+ void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
+ mLastAlarmDeliveryTime = nowELAPSED;
+ for (int i=0; i<triggerList.size(); i++) {
+ Alarm alarm = triggerList.get(i);
+ try {
+ if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
+ alarm.operation.send(getContext(), 0,
+ mBackgroundIntent.putExtra(
+ Intent.EXTRA_ALARM_COUNT, alarm.count),
+ mResultReceiver, mHandler);
+
+ // we have an active broadcast so stay awake.
+ if (mBroadcastRefCount == 0) {
+ setWakelockWorkSource(alarm.operation, alarm.workSource,
+ alarm.type, alarm.tag, true);
+ mWakeLock.acquire();
+ }
+ final InFlight inflight = new InFlight(AlarmManagerService.this,
+ alarm.operation, alarm.workSource, alarm.type, alarm.tag);
+ mInFlight.add(inflight);
+ mBroadcastRefCount++;
+
+ final BroadcastStats bs = inflight.mBroadcastStats;
+ bs.count++;
+ if (bs.nesting == 0) {
+ bs.nesting = 1;
+ bs.startTime = nowELAPSED;
+ } else {
+ bs.nesting++;
+ }
+ final FilterStats fs = inflight.mFilterStats;
+ fs.count++;
+ if (fs.nesting == 0) {
+ fs.nesting = 1;
+ fs.startTime = nowELAPSED;
+ } else {
+ fs.nesting++;
+ }
+ if (alarm.type == ELAPSED_REALTIME_WAKEUP
+ || alarm.type == RTC_WAKEUP) {
+ bs.numWakeup++;
+ fs.numWakeup++;
+ if (alarm.workSource != null && alarm.workSource.size() > 0) {
+ for (int wi=0; wi<alarm.workSource.size(); wi++) {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, alarm.workSource.get(wi),
+ alarm.workSource.getName(wi));
+ }
+ } else {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, -1, null);
+ }
+ }
+ } catch (PendingIntent.CanceledException e) {
+ if (alarm.repeatInterval > 0) {
+ // This IntentSender is no longer valid, but this
+ // is a repeating alarm, so toss the hoser.
+ removeImpl(alarm.operation);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure sending alarm.", e);
+ }
+ }
+ }
+
private class AlarmThread extends Thread
{
public AlarmThread()
@@ -1269,70 +1456,35 @@
}
}
- triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
- rescheduleKernelAlarmsLocked();
-
- // now deliver the alarm intents
- for (int i=0; i<triggerList.size(); i++) {
- Alarm alarm = triggerList.get(i);
- try {
- if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
- alarm.operation.send(getContext(), 0,
- mBackgroundIntent.putExtra(
- Intent.EXTRA_ALARM_COUNT, alarm.count),
- mResultReceiver, mHandler);
-
- // we have an active broadcast so stay awake.
- if (mBroadcastRefCount == 0) {
- setWakelockWorkSource(alarm.operation, alarm.workSource,
- alarm.type, true);
- mWakeLock.acquire();
- }
- final InFlight inflight = new InFlight(AlarmManagerService.this,
- alarm.operation, alarm.workSource, alarm.type);
- mInFlight.add(inflight);
- mBroadcastRefCount++;
-
- final BroadcastStats bs = inflight.mBroadcastStats;
- bs.count++;
- if (bs.nesting == 0) {
- bs.nesting = 1;
- bs.startTime = nowELAPSED;
- } else {
- bs.nesting++;
- }
- final FilterStats fs = inflight.mFilterStats;
- fs.count++;
- if (fs.nesting == 0) {
- fs.nesting = 1;
- fs.startTime = nowELAPSED;
- } else {
- fs.nesting++;
- }
- if (alarm.type == ELAPSED_REALTIME_WAKEUP
- || alarm.type == RTC_WAKEUP) {
- bs.numWakeup++;
- fs.numWakeup++;
- if (alarm.workSource != null && alarm.workSource.size() > 0) {
- for (int wi=0; wi<alarm.workSource.size(); wi++) {
- ActivityManagerNative.noteWakeupAlarm(
- alarm.operation, alarm.workSource.get(wi),
- alarm.workSource.getName(wi));
- }
- } else {
- ActivityManagerNative.noteWakeupAlarm(
- alarm.operation, -1, null);
- }
- }
- } catch (PendingIntent.CanceledException e) {
- if (alarm.repeatInterval > 0) {
- // This IntentSender is no longer valid, but this
- // is a repeating alarm, so toss the hoser.
- removeImpl(alarm.operation);
- }
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failure sending alarm.", e);
+ boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
+ if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
+ // if there are no wakeup alarms and the screen is off, we can
+ // delay what we have so far until the future.
+ if (mPendingNonWakeupAlarms.size() == 0) {
+ mStartCurrentDelayTime = nowELAPSED;
+ mNextNonWakeupDeliveryTime = nowELAPSED
+ + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
}
+ mPendingNonWakeupAlarms.addAll(triggerList);
+ mNumDelayedAlarms += triggerList.size();
+ rescheduleKernelAlarmsLocked();
+ } else {
+ // now deliver the alarm intents; if there are pending non-wakeup
+ // alarms, we need to merge them in to the list. note we don't
+ // just deliver them first because we generally want non-wakeup
+ // alarms delivered after wakeup alarms.
+ rescheduleKernelAlarmsLocked();
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ triggerList.addAll(mPendingNonWakeupAlarms);
+ Collections.sort(triggerList, mAlarmDispatchComparator);
+ final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+ mTotalDelayTime += thisDelayTime;
+ if (mMaxDelayTime < thisDelayTime) {
+ mMaxDelayTime = thisDelayTime;
+ }
+ mPendingNonWakeupAlarms.clear();
+ }
+ deliverAlarmsLocked(triggerList, nowELAPSED);
}
}
}
@@ -1344,14 +1496,13 @@
* @param pi PendingIntent to attribute blame to if ws is null.
* @param ws WorkSource to attribute blame.
*/
- void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, boolean first) {
+ void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
+ boolean first) {
try {
final boolean unimportant = pi == mTimeTickSender;
mWakeLock.setUnimportantForLogging(unimportant);
if (first || mLastWakeLockUnimportantForLogging) {
- mWakeLock.setHistoryTag(pi.getTag(
- type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
- ? "*walarm*:" : "*alarm*:"));
+ mWakeLock.setHistoryTag(tag);
} else {
mWakeLock.setHistoryTag(null);
}
@@ -1462,6 +1613,23 @@
}
}
+ class InteractiveStateReceiver extends BroadcastReceiver {
+ public InteractiveStateReceiver() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ getContext().registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
+ }
+ }
+ }
+
class UninstallReceiver extends BroadcastReceiver {
public UninstallReceiver() {
IntentFilter filter = new IntentFilter();
@@ -1589,7 +1757,7 @@
if (mInFlight.size() > 0) {
InFlight inFlight = mInFlight.get(0);
setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
- inFlight.mAlarmType, false);
+ inFlight.mAlarmType, inFlight.mTag, false);
} else {
// should never happen
mLog.w("Alarm wakelock still held but sent queue empty");
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 50553ee..5cb2a8a 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3439,7 +3439,7 @@
+ " mShowExplicitlyRequested=" + mShowExplicitlyRequested
+ " mShowForced=" + mShowForced
+ " mInputShown=" + mInputShown);
- p.println(" mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn);
+ p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
}
p.println(" ");
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index c32beda..cd8c13f 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -264,7 +264,7 @@
} else if (headset == BIT_USB_HEADSET_DGTL) {
device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
} else if (headset == BIT_HDMI_AUDIO) {
- device = AudioManager.DEVICE_OUT_AUX_DIGITAL;
+ device = AudioManager.DEVICE_OUT_HDMI;
} else {
Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);
return;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 61b3a89..46c5482 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11876,6 +11876,7 @@
pw.println(" cmd may be one of:");
pw.println(" l[ibraries]: list known shared libraries");
pw.println(" f[ibraries]: list device features");
+ pw.println(" k[eysets]: print known keysets");
pw.println(" r[esolvers]: dump intent resolvers");
pw.println(" perm[issions]: dump permissions");
pw.println(" pref[erred]: print preferred package settings");
@@ -11886,8 +11887,8 @@
pw.println(" m[essages]: print collected runtime messages");
pw.println(" v[erifiers]: print package verifier info");
pw.println(" version: print database version info");
+ pw.println(" write: write current settings now");
pw.println(" <package.name>: info about given package");
- pw.println(" k[eysets]: print known keysets");
return;
} else if ("--checkin".equals(opt)) {
checkin = true;
@@ -11938,6 +11939,12 @@
dumpState.setDump(DumpState.DUMP_VERSION);
} else if ("k".equals(cmd) || "keysets".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_KEYSETS);
+ } else if ("write".equals(cmd)) {
+ synchronized (mPackages) {
+ mSettings.writeLPr();
+ pw.println("Settings written.");
+ return;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index c20e38c..e2d2ac6 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -26,6 +26,7 @@
import android.os.IRemoteCallback;
import android.os.SystemProperties;
import android.util.Slog;
+import android.view.View;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -34,7 +35,6 @@
import android.view.animation.ClipRectAnimation;
import android.view.animation.Interpolator;
import android.view.animation.ScaleAnimation;
-
import android.view.animation.TranslateAnimation;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
@@ -500,7 +500,8 @@
*/
Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
int appHeight, int orientation, int transit,
- Rect containingFrame, Rect contentInsets) {
+ Rect containingFrame, Rect contentInsets,
+ boolean isFullScreen) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -520,6 +521,9 @@
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpFromClipRect.top = contentInsets.top;
+ }
mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
mTmpToClipRect.set(containingFrame);
} else {
@@ -527,7 +531,12 @@
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpFromClipRect.top = contentInsets.top;
+ mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
+ }
mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
mTmpToClipRect.set(containingFrame);
}
@@ -575,14 +584,22 @@
int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
mTmpToClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpToClipRect.top = contentInsets.top;
+ }
mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
} else {
// In landscape, we scale the height and clip to the top/left square
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
mTmpToClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpToClipRect.top = contentInsets.top;
+ mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+ }
mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
}
@@ -679,7 +696,7 @@
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
int appWidth, int appHeight, int orientation,
- Rect containingFrame, Rect contentInsets) {
+ Rect containingFrame, Rect contentInsets, boolean isFullScreen) {
Animation a;
if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -702,7 +719,7 @@
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
a = createAlternateThumbnailEnterExitAnimationLocked(
getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
- transit, containingFrame, contentInsets);
+ transit, containingFrame, contentInsets, isFullScreen);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
"ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c6fffbf..63a4f52 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -289,6 +289,11 @@
private static final int MAX_SCREENSHOT_RETRIES = 3;
+ // The flag describing a full screen app window (where the app takes care of drawing under the
+ // SystemUI bars)
+ private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -3193,8 +3198,11 @@
}
}
+ boolean isFullScreen =
+ ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
+ == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN);
Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
- mCurConfiguration.orientation, containingFrame, contentInsets);
+ mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen);
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a561fed..bc7742f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3682,4 +3682,43 @@
}
return false;
}
+
+ @Override
+ public void setGlobalSetting(ComponentName who, String setting, String value) {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ Settings.Global.putString(contentResolver, setting, value);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
+
+ @Override
+ public void setSecureSetting(ComponentName who, String setting, String value) {
+ int callingUserId = UserHandle.getCallingUserId();
+ final ContentResolver contentResolver = mContext.getContentResolver();
+
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putStringForUser(contentResolver, setting, value, callingUserId);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6be073c..55ae9c6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -639,18 +639,18 @@
}
try {
- mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
- } catch (Throwable e) {
- reportWtf("starting Wi-Fi PasspointService", e);
- }
-
- try {
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
}
try {
+ mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
+ } catch (Throwable e) {
+ reportWtf("starting Wi-Fi PasspointService", e);
+ }
+
+ try {
Slog.i(TAG, "Wi-Fi Scanning Service");
mSystemServiceManager.startService(
"com.android.server.wifi.WifiScanningService");