diff options
66 files changed, 657 insertions, 919 deletions
diff --git a/api/current.txt b/api/current.txt index a4893f9ed378..b61475db32d4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5494,7 +5494,6 @@ package android.app { public final class NotificationChannel implements android.os.Parcelable { ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int); - ctor public NotificationChannel(java.lang.String, int, int); ctor protected NotificationChannel(android.os.Parcel); method public boolean canBypassDnd(); method public boolean canShowBadge(); @@ -5508,7 +5507,6 @@ package android.app { method public int getLightColor(); method public int getLockscreenVisibility(); method public java.lang.CharSequence getName(); - method public int getNameResId(); method public android.net.Uri getSound(); method public long[] getVibrationPattern(); method public void setBypassDnd(boolean); @@ -5516,6 +5514,7 @@ package android.app { method public void setImportance(int); method public void setLightColor(int); method public void setLockscreenVisibility(int); + method public void setName(java.lang.CharSequence); method public void setShowBadge(boolean); method public void setSound(android.net.Uri, android.media.AudioAttributes); method public void setVibrationPattern(long[]); @@ -5528,14 +5527,12 @@ package android.app { public final class NotificationChannelGroup implements android.os.Parcelable { ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence); - ctor public NotificationChannelGroup(java.lang.String, int); ctor protected NotificationChannelGroup(android.os.Parcel); method public android.app.NotificationChannelGroup clone(); method public int describeContents(); method public java.util.List<android.app.NotificationChannel> getChannels(); method public java.lang.String getId(); method public java.lang.CharSequence getName(); - method public int getNameResId(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR; } @@ -5551,12 +5548,14 @@ package android.app { method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>); method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>); method public void deleteNotificationChannel(java.lang.String); + method public void deleteNotificationChannelGroup(java.lang.String); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); method public int getImportance(); method public android.app.NotificationChannel getNotificationChannel(java.lang.String); + method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(); method public java.util.List<android.app.NotificationChannel> getNotificationChannels(); method public android.app.NotificationManager.Policy getNotificationPolicy(); method public boolean isNotificationPolicyAccessGranted(); diff --git a/api/system-current.txt b/api/system-current.txt index cf4902c4e18d..ddfc1ccd8908 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5681,7 +5681,6 @@ package android.app { public final class NotificationChannel implements android.os.Parcelable { ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int); - ctor public NotificationChannel(java.lang.String, int, int); ctor protected NotificationChannel(android.os.Parcel); method public boolean canBypassDnd(); method public boolean canShowBadge(); @@ -5695,19 +5694,17 @@ package android.app { method public int getLightColor(); method public int getLockscreenVisibility(); method public java.lang.CharSequence getName(); - method public int getNameResId(); method public android.net.Uri getSound(); method public int getUserLockedFields(); method public long[] getVibrationPattern(); method public boolean isDeleted(); - method public void lockFields(int); method public void populateFromXml(org.xmlpull.v1.XmlPullParser); method public void setBypassDnd(boolean); - method public void setDeleted(boolean); method public void setGroup(java.lang.String); method public void setImportance(int); method public void setLightColor(int); method public void setLockscreenVisibility(int); + method public void setName(java.lang.CharSequence); method public void setShowBadge(boolean); method public void setSound(android.net.Uri, android.media.AudioAttributes); method public void setVibrationPattern(long[]); @@ -5732,18 +5729,14 @@ package android.app { public final class NotificationChannelGroup implements android.os.Parcelable { ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence); - ctor public NotificationChannelGroup(java.lang.String, int); ctor protected NotificationChannelGroup(android.os.Parcel); - method public void addChannel(android.app.NotificationChannel); method public android.app.NotificationChannelGroup clone(); method public int describeContents(); method public java.util.List<android.app.NotificationChannel> getChannels(); method public java.lang.String getId(); method public java.lang.CharSequence getName(); - method public int getNameResId(); method public org.json.JSONObject toJson() throws org.json.JSONException; method public void writeToParcel(android.os.Parcel, int); - method public void writeXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException; field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR; } @@ -5758,12 +5751,14 @@ package android.app { method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>); method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>); method public void deleteNotificationChannel(java.lang.String); + method public void deleteNotificationChannelGroup(java.lang.String); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules(); method public final int getCurrentInterruptionFilter(); method public int getImportance(); method public android.app.NotificationChannel getNotificationChannel(java.lang.String); + method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(); method public java.util.List<android.app.NotificationChannel> getNotificationChannels(); method public android.app.NotificationManager.Policy getNotificationPolicy(); method public boolean isNotificationPolicyAccessGranted(); diff --git a/api/test-current.txt b/api/test-current.txt index bb8b4540a9fd..fe6769673541 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5504,7 +5504,6 @@ package android.app { public final class NotificationChannel implements android.os.Parcelable { ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int); - ctor public NotificationChannel(java.lang.String, int, int); ctor protected NotificationChannel(android.os.Parcel); method public boolean canBypassDnd(); method public boolean canShowBadge(); @@ -5518,7 +5517,6 @@ package android.app { method public int getLightColor(); method public int getLockscreenVisibility(); method public java.lang.CharSequence getName(); - method public int getNameResId(); method public android.net.Uri getSound(); method public long[] getVibrationPattern(); method public void setBypassDnd(boolean); @@ -5526,6 +5524,7 @@ package android.app { method public void setImportance(int); method public void setLightColor(int); method public void setLockscreenVisibility(int); + method public void setName(java.lang.CharSequence); method public void setShowBadge(boolean); method public void setSound(android.net.Uri, android.media.AudioAttributes); method public void setVibrationPattern(long[]); @@ -5538,14 +5537,12 @@ package android.app { public final class NotificationChannelGroup implements android.os.Parcelable { ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence); - ctor public NotificationChannelGroup(java.lang.String, int); ctor protected NotificationChannelGroup(android.os.Parcel); method public android.app.NotificationChannelGroup clone(); method public int describeContents(); method public java.util.List<android.app.NotificationChannel> getChannels(); method public java.lang.String getId(); method public java.lang.CharSequence getName(); - method public int getNameResId(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR; } @@ -5561,6 +5558,7 @@ package android.app { method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>); method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>); method public void deleteNotificationChannel(java.lang.String); + method public void deleteNotificationChannelGroup(java.lang.String); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String); method public java.util.Map<java.lang.String, android.app.AutomaticZenRule> getAutomaticZenRules(); @@ -5568,6 +5566,7 @@ package android.app { method public android.content.ComponentName getEffectsSuppressor(); method public int getImportance(); method public android.app.NotificationChannel getNotificationChannel(java.lang.String); + method public java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(); method public java.util.List<android.app.NotificationChannel> getNotificationChannels(); method public android.app.NotificationManager.Policy getNotificationPolicy(); method public boolean isNotificationPolicyAccessGranted(); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index e5df278f2cc1..75d4f32055e2 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -21,8 +21,11 @@ import static android.Manifest.permission.GET_ACCOUNTS; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; +import android.annotation.SdkConstant; import android.annotation.Size; import android.annotation.SystemApi; +import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.BroadcastBehavior; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -335,6 +338,8 @@ public class AccountManager { * * @deprecated use #addOnAccountsUpdatedListener to get account updates in runtime. */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(includeBackground = true) public static final String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; diff --git a/core/java/android/annotation/BroadcastBehavior.java b/core/java/android/annotation/BroadcastBehavior.java new file mode 100644 index 000000000000..9b2ca3120290 --- /dev/null +++ b/core/java/android/annotation/BroadcastBehavior.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 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.annotation; + +import android.content.Intent; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Description of how the annotated broadcast action behaves. + * + * @hide + */ +@Target({ ElementType.FIELD }) +@Retention(RetentionPolicy.SOURCE) +public @interface BroadcastBehavior { + /** + * This broadcast will only be delivered to an explicit target. + * + * @see Intent#setPackage(String) + * @see Intent#setComponent(android.content.ComponentName) + */ + boolean explicitOnly() default false; + + /** + * This broadcast will only be delivered to registered receivers. + * + * @see Intent#FLAG_RECEIVER_REGISTERED_ONLY + */ + boolean registeredOnly() default false; + + /** + * This broadcast will include all {@code AndroidManifest.xml} receivers + * regardless of process state. + * + * @see Intent#FLAG_RECEIVER_INCLUDE_BACKGROUND + */ + boolean includeBackground() default false; +} diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 44cc5b408f50..5cdfb8e3414e 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -50,6 +50,7 @@ import android.database.sqlite.SQLiteDebug; import android.database.sqlite.SQLiteDebug.DbStats; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Typeface; import android.hardware.display.DisplayManagerGlobal; import android.net.ConnectivityManager; import android.net.IConnectivityManager; @@ -5665,6 +5666,7 @@ public final class ActivityThread { } // Preload fonts resources + Typeface.setApplicationContext(appContext); try { final ApplicationInfo info = getPackageManager().getApplicationInfo( diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 5ab767ba9676..5ea24804e0fd 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -66,6 +66,9 @@ interface INotificationManager ParceledListSlice getNotificationChannels(String pkg); ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted); int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted); + int getDeletedChannelCount(String pkg, int uid); + void deleteNotificationChannelGroup(String pkg, String channelGroupId); + ParceledListSlice getNotificationChannelGroups(String pkg); // TODO: Remove this when callers have been migrated to the equivalent // INotificationListener method. diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 16c85f587956..29c4520ffdcb 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringRes; import android.annotation.SystemApi; +import android.content.Intent; import android.media.AudioAttributes; import android.net.Uri; import android.os.Parcel; @@ -47,7 +48,6 @@ public final class NotificationChannel implements Parcelable { private static final String TAG_CHANNEL = "channel"; private static final String ATT_NAME = "name"; - private static final String ATT_NAME_RES_ID = "name_res_id"; private static final String ATT_ID = "id"; private static final String ATT_DELETED = "deleted"; private static final String ATT_PRIORITY = "priority"; @@ -141,7 +141,6 @@ public final class NotificationChannel implements Parcelable { private final String mId; private CharSequence mName; - private int mNameResId = 0; private int mImportance = DEFAULT_IMPORTANCE; private boolean mBypassDnd; private int mLockscreenVisibility = DEFAULT_VISIBILITY; @@ -162,7 +161,9 @@ public final class NotificationChannel implements Parcelable { * @param id The id of the channel. Must be unique per package. * @param name The user visible name of the channel. Unchangeable once created; use this * constructor if the channel represents a user-defined category that does not - * need to be translated. + * need to be translated. You can rename this channel when the system + * locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED} + * broadcast. * @param importance The importance of the channel. This controls how interruptive notifications * posted to this channel are. See e.g. * {@link NotificationManager#IMPORTANCE_DEFAULT}. @@ -173,21 +174,6 @@ public final class NotificationChannel implements Parcelable { this.mImportance = importance; } - /** - * Creates a notification channel. - * - * @param id The id of the channel. Must be unique per package. - * @param nameResId The resource id of the string containing the channel name. - * @param importance The importance of the channel. This controls how interruptive notifications - * posted to this channel are. See e.g. - * {@link NotificationManager#IMPORTANCE_DEFAULT}. - */ - public NotificationChannel(String id, @StringRes int nameResId, int importance) { - this.mId = id; - this.mNameResId = nameResId; - this.mImportance = importance; - } - protected NotificationChannel(Parcel in) { if (in.readByte() != 0) { mId = in.readString(); @@ -195,7 +181,6 @@ public final class NotificationChannel implements Parcelable { mId = null; } mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mNameResId = in.readInt(); mImportance = in.readInt(); mBypassDnd = in.readByte() != 0; mLockscreenVisibility = in.readInt(); @@ -228,7 +213,6 @@ public final class NotificationChannel implements Parcelable { dest.writeByte((byte) 0); } TextUtils.writeToParcel(mName, dest, flags); - dest.writeInt(mNameResId); dest.writeInt(mImportance); dest.writeByte(mBypassDnd ? (byte) 1 : (byte) 0); dest.writeInt(mLockscreenVisibility); @@ -262,7 +246,6 @@ public final class NotificationChannel implements Parcelable { /** * @hide */ - @SystemApi public void lockFields(int field) { mUserLockedFields |= field; } @@ -270,16 +253,15 @@ public final class NotificationChannel implements Parcelable { /** * @hide */ - @SystemApi public void setDeleted(boolean deleted) { mDeleted = deleted; } /** - * @hide + * Sets the name of this channel. */ - public void setNameResId(@StringRes int nameResId) { - this.mNameResId = nameResId; + public void setName(CharSequence name) { + mName = name; } // Modifiable by a notification ranker. @@ -417,13 +399,6 @@ public final class NotificationChannel implements Parcelable { } /** - * Returns the resource id of the user visible name of this channel. - */ - public int getNameResId() { - return mNameResId; - } - - /** * Returns the user specified importance {e.g. @link NotificationManager#IMPORTANCE_LOW} for * notifications posted to this channel. */ @@ -556,7 +531,6 @@ public final class NotificationChannel implements Parcelable { if (getName() != null) { out.attribute(null, ATT_NAME, getName().toString()); } - out.attribute(null, ATT_NAME_RES_ID, Integer.toString(getNameResId())); if (getImportance() != DEFAULT_IMPORTANCE) { out.attribute( null, ATT_IMPORTANCE, Integer.toString(getImportance())); @@ -614,7 +588,6 @@ public final class NotificationChannel implements Parcelable { JSONObject record = new JSONObject(); record.put(ATT_ID, getId()); record.put(ATT_NAME, getName()); - record.put(ATT_NAME_RES_ID, getNameResId()); if (getImportance() != DEFAULT_IMPORTANCE) { record.put(ATT_IMPORTANCE, NotificationListenerService.Ranking.importanceToString(getImportance())); @@ -732,7 +705,6 @@ public final class NotificationChannel implements Parcelable { NotificationChannel that = (NotificationChannel) o; - if (getNameResId() != that.getNameResId()) return false; if (getImportance() != that.getImportance()) return false; if (mBypassDnd != that.mBypassDnd) return false; if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false; @@ -762,7 +734,6 @@ public final class NotificationChannel implements Parcelable { public int hashCode() { int result = getId() != null ? getId().hashCode() : 0; result = 31 * result + (getName() != null ? getName().hashCode() : 0); - result = 31 * result + getNameResId(); result = 31 * result + getImportance(); result = 31 * result + (mBypassDnd ? 1 : 0); result = 31 * result + getLockscreenVisibility(); @@ -784,7 +755,6 @@ public final class NotificationChannel implements Parcelable { return "NotificationChannel{" + "mId='" + mId + '\'' + ", mName=" + mName + - ", mNameResId=" + mNameResId + ", mImportance=" + mImportance + ", mBypassDnd=" + mBypassDnd + ", mLockscreenVisibility=" + mLockscreenVisibility + diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 288d39a706f9..2b0cd0442a0a 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -17,6 +17,7 @@ package android.app; import android.annotation.StringRes; import android.annotation.SystemApi; +import android.content.Intent; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -41,38 +42,25 @@ public final class NotificationChannelGroup implements Parcelable { private static final String TAG_GROUP = "channelGroup"; private static final String ATT_NAME = "name"; - private static final String ATT_NAME_RES_ID = "name_res_id"; private static final String ATT_ID = "id"; private final String mId; private CharSequence mName; - private int mNameResId = 0; private List<NotificationChannel> mChannels = new ArrayList<>(); /** - * Creates a notification channel. + * Creates a notification channel group. * * @param id The id of the group. Must be unique per package. - * @param name The user visible name of the group. Unchangeable once created; use this - * constructor if the group represents something user-defined that does not - * need to be translated. + * @param name The user visible name of the group. You can rename this group when the system + * locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED} + * broadcast. */ public NotificationChannelGroup(String id, CharSequence name) { this.mId = id; this.mName = name; } - /** - * Creates a notification channel. - * - * @param id The id of the group. Must be unique per package. - * @param nameResId String resource id of the user visible name of the group. - */ - public NotificationChannelGroup(String id, @StringRes int nameResId) { - this.mId = id; - this.mNameResId = nameResId; - } - protected NotificationChannelGroup(Parcel in) { if (in.readByte() != 0) { mId = in.readString(); @@ -80,7 +68,6 @@ public final class NotificationChannelGroup implements Parcelable { mId = null; } mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mNameResId = in.readInt(); in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader()); } @@ -93,7 +80,6 @@ public final class NotificationChannelGroup implements Parcelable { dest.writeByte((byte) 0); } TextUtils.writeToParcel(mName, dest, flags); - dest.writeInt(mNameResId); dest.writeParcelableList(mChannels, flags); } @@ -111,19 +97,11 @@ public final class NotificationChannelGroup implements Parcelable { return mName; } - /** - * Returns the resource id of the user visible name of this group. - */ - public @StringRes int getNameResId() { - return mNameResId; - } - /* * Returns the list of channels that belong to this group * * @hide */ - @SystemApi public List<NotificationChannel> getChannels() { return mChannels; } @@ -131,7 +109,6 @@ public final class NotificationChannelGroup implements Parcelable { /** * @hide */ - @SystemApi public void addChannel(NotificationChannel channel) { mChannels.add(channel); } @@ -139,7 +116,6 @@ public final class NotificationChannelGroup implements Parcelable { /** * @hide */ - @SystemApi public void writeXml(XmlSerializer out) throws IOException { out.startTag(null, TAG_GROUP); @@ -147,9 +123,6 @@ public final class NotificationChannelGroup implements Parcelable { if (getName() != null) { out.attribute(null, ATT_NAME, getName().toString()); } - if (getNameResId() != 0) { - out.attribute(null, ATT_NAME_RES_ID, Integer.toString(getNameResId())); - } out.endTag(null, TAG_GROUP); } @@ -162,7 +135,6 @@ public final class NotificationChannelGroup implements Parcelable { JSONObject record = new JSONObject(); record.put(ATT_ID, getId()); record.put(ATT_NAME, getName()); - record.put(ATT_NAME_RES_ID, getNameResId()); return record; } @@ -191,31 +163,22 @@ public final class NotificationChannelGroup implements Parcelable { NotificationChannelGroup that = (NotificationChannelGroup) o; - if (getNameResId() != that.getNameResId()) return false; if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false; if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) { return false; } - return getChannels() != null ? getChannels().equals(that.getChannels()) - : that.getChannels() == null; - + return true; } @Override public NotificationChannelGroup clone() { - if (getName() != null) { - return new NotificationChannelGroup(getId(), getName()); - } else { - return new NotificationChannelGroup(getId(), getNameResId()); - } + return new NotificationChannelGroup(getId(), getName()); } @Override public int hashCode() { int result = getId() != null ? getId().hashCode() : 0; result = 31 * result + (getName() != null ? getName().hashCode() : 0); - result = 31 * result + getNameResId(); - result = 31 * result + (getChannels() != null ? getChannels().hashCode() : 0); return result; } @@ -224,7 +187,6 @@ public final class NotificationChannelGroup implements Parcelable { return "NotificationChannelGroup{" + "mId='" + mId + '\'' + ", mName=" + mName + - ", mNameResId=" + mNameResId + ", mChannels=" + mChannels + '}'; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 2296838eddb3..0379970762ab 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -385,7 +385,7 @@ public class NotificationManager /** * Creates a group container for {@link NotificationChannel} objects. * - * This is a no-op for groups that already exist. + * This can be used to rename an existing group. * <p> * Group information is only used for presentation, not for behavior. Groups are optional * for channels, and you can have a mix of channels that belong to groups and channels @@ -421,21 +421,22 @@ public class NotificationManager /** * Creates a notification channel that notifications can be posted to. * - * This is a no-op for channels that already exist. + * This can also be used to restore a deleted channel and to rename an existing channel. All + * other fields are ignored for channels that already exist. * * @param channel the channel to create. Note that the created channel may differ from this * value. If the provided channel is malformed, a RemoteException will be - * thrown. If the channel already exists, it will not be modified. + * thrown. */ public void createNotificationChannel(@NonNull NotificationChannel channel) { createNotificationChannels(Arrays.asList(channel)); } /** - * Creates multiple notification channels that different notifications can be posted to. + * Creates multiple notification channels that different notifications can be posted to. See + * {@link #createNotificationChannel(NotificationChannel)}. * - * @param channels the list of channels to attempt to create. If any of these channels already - * exist, they will not be modified. + * @param channels the list of channels to attempt to create. */ public void createNotificationChannels(@NonNull List<NotificationChannel> channels) { INotificationManager service = getService(); @@ -497,6 +498,30 @@ public class NotificationManager } /** + * Returns all notification channel groups belonging to the calling app. + */ + public List<NotificationChannelGroup> getNotificationChannelGroups() { + INotificationManager service = getService(); + try { + return service.getNotificationChannelGroups(mContext.getPackageName()).getList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Deletes the given notification channel group. + */ + public void deleteNotificationChannelGroup(String groupId) { + INotificationManager service = getService(); + try { + service.deleteNotificationChannelGroup(mContext.getPackageName(), groupId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * @hide */ @TestApi diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index 0fb59668a201..d9b6eed4fc4d 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -17,6 +17,7 @@ package android.app.admin; import android.accounts.AccountManager; +import android.annotation.BroadcastBehavior; import android.annotation.IntDef; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -81,6 +82,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * that other applications can not abuse it. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED"; @@ -94,6 +96,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * to the user before they disable your admin. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED"; @@ -115,6 +118,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * its intent filter. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"; @@ -131,6 +135,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED"; @@ -147,6 +152,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED"; @@ -160,6 +166,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED"; @@ -173,6 +180,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * this broadcast. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING"; @@ -187,6 +195,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @see DevicePolicyManager#isLockTaskPermitted(String) */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_LOCK_TASK_ENTERING = "android.app.action.LOCK_TASK_ENTERING"; @@ -200,6 +209,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @see DevicePolicyManager#isLockTaskPermitted(String) */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_LOCK_TASK_EXITING = "android.app.action.LOCK_TASK_EXITING"; @@ -232,6 +242,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * <p>Output: Nothing</p> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE"; @@ -244,6 +255,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_BUGREPORT_SHARING_DECLINED = "android.app.action.BUGREPORT_SHARING_DECLINED"; @@ -256,6 +268,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_BUGREPORT_FAILED = "android.app.action.BUGREPORT_FAILED"; /** @@ -266,6 +279,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_BUGREPORT_SHARE = "android.app.action.BUGREPORT_SHARE"; @@ -274,6 +288,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_SECURITY_LOGS_AVAILABLE = "android.app.action.SECURITY_LOGS_AVAILABLE"; @@ -283,6 +298,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_NETWORK_LOGS_AVAILABLE = "android.app.action.NETWORK_LOGS_AVAILABLE"; @@ -314,7 +330,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_USER_ADDED = "android.app.action.USER_ADDED"; + @BroadcastBehavior(explicitOnly = true) + public static final String ACTION_USER_ADDED = "android.app.action.USER_ADDED"; /** * Broadcast action: notify the device owner that a user or profile has been removed. @@ -323,6 +340,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_USER_REMOVED = "android.app.action.USER_REMOVED"; /** @@ -401,6 +419,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE = "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE"; diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 67c791df3c9a..74a39e85e029 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -16,8 +16,11 @@ package android.appwidget; +import android.annotation.BroadcastBehavior; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -81,12 +84,14 @@ public class AppWidgetManager { * * @see #ACTION_APPWIDGET_CONFIGURE */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK"; /** * Similar to ACTION_APPWIDGET_PICK, but used from keyguard * @hide */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_KEYGUARD_APPWIDGET_PICK = "android.appwidget.action.KEYGUARD_APPWIDGET_PICK"; @@ -133,6 +138,7 @@ public class AppWidgetManager { * @see #ACTION_APPWIDGET_CONFIGURE * */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_APPWIDGET_BIND = "android.appwidget.action.APPWIDGET_BIND"; /** @@ -157,6 +163,7 @@ public class AppWidgetManager { * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED} * broadcast. */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE"; /** @@ -290,6 +297,8 @@ public class AppWidgetManager { * * @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE"; /** @@ -302,6 +311,8 @@ public class AppWidgetManager { * AppWidgetProvider.onAppWidgetOptionsChanged(Context context, * AppWidgetManager appWidgetManager, int appWidgetId, Bundle newExtras) */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"; /** @@ -312,6 +323,8 @@ public class AppWidgetManager { * * @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds) */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED"; /** @@ -322,6 +335,8 @@ public class AppWidgetManager { * * @see AppWidgetProvider#onEnabled AppWidgetProvider.onDisabled(Context context) */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED"; /** @@ -334,6 +349,8 @@ public class AppWidgetManager { * * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context) */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED"; /** @@ -365,6 +382,8 @@ public class AppWidgetManager { * * @see #ACTION_APPWIDGET_HOST_RESTORED */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_APPWIDGET_RESTORED = "android.appwidget.action.APPWIDGET_RESTORED"; @@ -402,6 +421,8 @@ public class AppWidgetManager { * * @see #ACTION_APPWIDGET_RESTORED */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(explicitOnly = true) public static final String ACTION_APPWIDGET_HOST_RESTORED = "android.appwidget.action.APPWIDGET_HOST_RESTORED"; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 1f01e28ea0b0..4dc6fd227243 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -17,6 +17,7 @@ package android.content; import android.annotation.AnyRes; +import android.annotation.BroadcastBehavior; import android.annotation.IntDef; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -1992,6 +1993,7 @@ public class Intent implements Parcelable, Cloneable { * This is a protected intent that can only be sent by the system. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @BroadcastBehavior(includeBackground = true) public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"; /** diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index e15a0e240711..5a28e87ac65f 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -211,6 +211,14 @@ public class PackageParser { CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT); } + private static final boolean LOG_UNSAFE_BROADCASTS = false; + + // Set of broadcast actions that are safe for manifest receivers + private static final Set<String> SAFE_BROADCASTS = new ArraySet<>(); + static { + SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED); + } + /** @hide */ public static class NewPermissionInfo { public final String name; @@ -4247,6 +4255,18 @@ public class PackageParser { if (intent.isVisibleToInstantApp()) { a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL; } + if (LOG_UNSAFE_BROADCASTS && receiver + && (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O)) { + for (int i = 0; i < intent.countActions(); i++) { + final String action = intent.getAction(i); + if (action == null || !action.startsWith("android.")) continue; + if (!SAFE_BROADCASTS.contains(action)) { + Slog.w(TAG, "Broadcast " + action + " may never be delivered to " + + owner.packageName + " as requested at: " + + parser.getPositionDescription()); + } + } + } } else if (!receiver && parser.getName().equals("preferred")) { ActivityIntentInfo intent = new ActivityIntentInfo(a); if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/, diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java index 1b1b958dce9b..4faff62c2655 100644 --- a/core/java/android/net/ConnectivityMetricsEvent.java +++ b/core/java/android/net/ConnectivityMetricsEvent.java @@ -19,20 +19,32 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; -/** {@hide} */ +/** + * Represents a core networking event defined in package android.net.metrics. + * Logged by IpConnectivityLog and managed by ConnectivityMetrics service. + * {@hide} + * */ public final class ConnectivityMetricsEvent implements Parcelable { - /** The time when this event was collected, as returned by System.currentTimeMillis(). */ + /** Time when this event was collected, as returned by System.currentTimeMillis(). */ public long timestamp; - + /** Transports of the network associated with the event, as defined in NetworkCapabilities. */ + public long transports; + /** Network id of the network associated with the event, or 0 if unspecified. */ + public int netId; + /** Name of the network interface associated with the event, or null if unspecified. */ + public String ifname; /** Opaque event-specific data. */ public Parcelable data; public ConnectivityMetricsEvent() { } - public ConnectivityMetricsEvent(Parcel in) { + private ConnectivityMetricsEvent(Parcel in) { timestamp = in.readLong(); + transports = in.readLong(); + netId = in.readInt(); + ifname = in.readString(); data = in.readParcelable(null); } @@ -56,11 +68,15 @@ public final class ConnectivityMetricsEvent implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(timestamp); + dest.writeLong(transports); + dest.writeInt(netId); + dest.writeString(ifname); dest.writeParcelable(data, 0); } @Override public String toString() { + // TODO: add transports, netId, ifname return String.format("ConnectivityMetricsEvent(%tT.%tL): %s", timestamp, timestamp, data); } } diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java index aaad1fa68267..79094c02b272 100644 --- a/core/java/android/net/metrics/IpConnectivityLog.java +++ b/core/java/android/net/metrics/IpConnectivityLog.java @@ -60,23 +60,22 @@ public class IpConnectivityLog { } /** - * Log an IpConnectivity event. - * @param timestamp is the epoch timestamp of the event in ms. - * @param data is a Parcelable instance representing the event. + * Log a ConnectivityMetricsEvent. + * @param ev the event to log. If the event timestamp is 0, + * the timestamp is set to the current time in milliseconds. * @return true if the event was successfully logged. */ - public boolean log(long timestamp, Parcelable data) { + public boolean log(ConnectivityMetricsEvent ev) { if (!checkLoggerService()) { if (DBG) { Log.d(TAG, SERVICE_NAME + " service was not ready"); } return false; } - + if (ev.timestamp == 0) { + ev.timestamp = System.currentTimeMillis(); + } try { - ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent(); - ev.timestamp = timestamp; - ev.data = data; int left = mService.logEvent(ev); return left >= 0; } catch (RemoteException e) { @@ -85,7 +84,31 @@ public class IpConnectivityLog { } } - public void log(Parcelable event) { - log(System.currentTimeMillis(), event); + /** + * Log an IpConnectivity event. + * @param timestamp is the epoch timestamp of the event in ms. + * If the timestamp is 0, the timestamp is set to the current time in milliseconds. + * @param data is a Parcelable instance representing the event. + * @return true if the event was successfully logged. + */ + public boolean log(long timestamp, Parcelable data) { + ConnectivityMetricsEvent ev = makeEv(data); + ev.timestamp = timestamp; + return log(ev); + } + + /** + * Log an IpConnectivity event. + * @param data is a Parcelable instance representing the event. + * @return true if the event was successfully logged. + */ + public boolean log(Parcelable data) { + return log(makeEv(data)); + } + + private static ConnectivityMetricsEvent makeEv(Parcelable data) { + ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent(); + ev.data = data; + return ev; } } diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index b525193c1b9c..8632194f2b02 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -35,6 +35,12 @@ public class SystemProperties { private static final String TAG = "SystemProperties"; private static final boolean TRACK_KEY_ACCESS = false; + /** + * Android O removed the property name length limit, but com.amazon.kindle 7.8.1.5 + * uses reflection to read this whenever text is selected (http://b/36095274). + */ + public static final int PROP_NAME_MAX = Integer.MAX_VALUE; + public static final int PROP_VALUE_MAX = 91; private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>(); diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java index 9f5d9d45c974..84443e9e3f55 100644 --- a/core/java/android/provider/FontsContract.java +++ b/core/java/android/provider/FontsContract.java @@ -138,12 +138,8 @@ public class FontsContract { private HandlerThread mThread; /** @hide */ - public FontsContract() { - // TODO: investigate if the system context is the best option here. ApplicationContext or - // the one passed by developer? - // TODO: Looks like ActivityThread.currentActivityThread() can return null. Check when it - // returns null and check if we need to handle null case. - mContext = ActivityThread.currentActivityThread().getSystemContext(); + public FontsContract(Context context) { + mContext = context.getApplicationContext(); mPackageManager = mContext.getPackageManager(); } diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 1facc106d645..7e6af11a62c7 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -98,31 +98,6 @@ interface IWindowSession { out Rect outOutsets, out Rect outBackdropFrame, out Configuration outConfig, out Surface outSurface); - /** - * Position a window relative to it's parent (attached) window without triggering - * a full relayout. This action may be deferred until a given frame number - * for the parent window appears. This allows for synchronizing movement of a child - * to repainting the contents of the parent. - * - * "width" and "height" correspond to the width and height members of - * WindowManager.LayoutParams in the {@link #relayout relayout()} case. - * This may differ from the surface buffer size in the - * case of {@link LayoutParams#FLAG_SCALED} and {@link #relayout relayout()} - * must be used with requestedWidth/height if this must be changed. - * - * @param window The window being modified. Must be attached to a parent window - * or this call will fail. - * @param left The new left position - * @param top The new top position - * @param right The new right position - * @param bottom The new bottom position - * @param deferTransactionUntilFrame Frame number from our parent (attached) to - * defer this action until. - * @param outFrame Rect in which is placed the new position/size on screen. - */ - void repositionChild(IWindow childWindow, int left, int top, int right, int bottom, - long deferTransactionUntilFrame, out Rect outFrame); - /* * Notify the window manager that an application is relaunching and * windows should be prepared for replacement. @@ -134,12 +109,6 @@ interface IWindowSession { void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly); /** - * If a call to relayout() asked to have the surface destroy deferred, - * it must call this once it is okay to destroy that surface. - */ - void performDeferredDestroy(IWindow window); - - /** * Called by a client to report that it ran out of graphics memory. */ boolean outOfMemory(IWindow window); diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index ec3aac21cb19..c840f26a0d53 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -48,12 +48,12 @@ public class SystemNotificationChannels { List<NotificationChannel> channelsList = new ArrayList<NotificationChannel>(); channelsList.add(new NotificationChannel( VIRTUAL_KEYBOARD, - R.string.notification_channel_virtual_keyboard, + context.getString(R.string.notification_channel_virtual_keyboard), NotificationManager.IMPORTANCE_LOW)); final NotificationChannel physicalKeyboardChannel = new NotificationChannel( PHYSICAL_KEYBOARD, - R.string.notification_channel_physical_keyboard, + context.getString(R.string.notification_channel_physical_keyboard), NotificationManager.IMPORTANCE_DEFAULT); physicalKeyboardChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, Notification.AUDIO_ATTRIBUTES_DEFAULT); @@ -61,32 +61,32 @@ public class SystemNotificationChannels { channelsList.add(new NotificationChannel( SECURITY, - R.string.notification_channel_security, + context.getString(R.string.notification_channel_security), NotificationManager.IMPORTANCE_LOW)); channelsList.add(new NotificationChannel( CAR_MODE, - R.string.notification_channel_car_mode, + context.getString(R.string.notification_channel_car_mode), NotificationManager.IMPORTANCE_LOW)); channelsList.add(new NotificationChannel( DEVELOPER, - R.string.notification_channel_developer, + context.getString(R.string.notification_channel_developer), NotificationManager.IMPORTANCE_LOW)); channelsList.add(new NotificationChannel( UPDATES, - R.string.notification_channel_updates, + context.getString(R.string.notification_channel_updates), NotificationManager.IMPORTANCE_LOW)); channelsList.add(new NotificationChannel( NETWORK_STATUS, - R.string.notification_channel_network_status, + context.getString(R.string.notification_channel_network_status), NotificationManager.IMPORTANCE_LOW)); final NotificationChannel networkAlertsChannel = new NotificationChannel( NETWORK_ALERTS, - R.string.notification_channel_network_alerts, + context.getString(R.string.notification_channel_network_alerts), NotificationManager.IMPORTANCE_HIGH); networkAlertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, Notification.AUDIO_ATTRIBUTES_DEFAULT); @@ -94,17 +94,17 @@ public class SystemNotificationChannels { channelsList.add(new NotificationChannel( VPN, - R.string.notification_channel_vpn, + context.getString(R.string.notification_channel_vpn), NotificationManager.IMPORTANCE_LOW)); channelsList.add(new NotificationChannel( DEVICE_ADMIN, - R.string.notification_channel_device_admin, + context.getString(R.string.notification_channel_device_admin), NotificationManager.IMPORTANCE_LOW)); final NotificationChannel alertsChannel = new NotificationChannel( ALERTS, - R.string.notification_channel_alerts, + context.getString(R.string.notification_channel_alerts), NotificationManager.IMPORTANCE_DEFAULT); alertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, Notification.AUDIO_ATTRIBUTES_DEFAULT); @@ -112,12 +112,12 @@ public class SystemNotificationChannels { channelsList.add(new NotificationChannel( RETAIL_MODE, - R.string.notification_channel_retail_mode, + context.getString(R.string.notification_channel_retail_mode), NotificationManager.IMPORTANCE_LOW)); channelsList.add(new NotificationChannel( USB, - R.string.notification_channel_usb, + context.getString(R.string.notification_channel_usb), NotificationManager.IMPORTANCE_MIN)); nm.createNotificationChannels(channelsList); @@ -128,7 +128,7 @@ public class SystemNotificationChannels { final NotificationManager nm = context.getSystemService(NotificationManager.class); nm.createNotificationChannelsForPackage(pkg, Arrays.asList(new NotificationChannel( ACCOUNT, - R.string.notification_channel_account, + context.getString(R.string.notification_channel_account), NotificationManager.IMPORTANCE_LOW))); } diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java index 96468abd9047..0a9faa15dcc2 100644 --- a/core/java/com/android/internal/os/WrapperInit.java +++ b/core/java/com/android/internal/os/WrapperInit.java @@ -142,6 +142,21 @@ public class WrapperInit { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from wrapper"); } - RuntimeInit.applicationInit(targetSdkVersion, argv, null); + // Check whether the first argument is a "-cp" in argv, and assume the next argument is the + // classpath. If found, create a PathClassLoader and use it for applicationInit. + ClassLoader classLoader = null; + if (argv != null && argv.length > 2 && argv[0].equals("-cp")) { + classLoader = ZygoteInit.createPathClassLoader(argv[1], targetSdkVersion); + + // Install this classloader as the context classloader, too. + Thread.currentThread().setContextClassLoader(classLoader); + + // Remove the classpath from the arguments. + String removedArgs[] = new String[argv.length - 2]; + System.arraycopy(argv, 2, removedArgs, 0, argv.length - 2); + argv = removedArgs; + } + + RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); } } diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 76d8af1a509d..b2a2fec879e6 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -468,7 +468,8 @@ public class ZygoteInit { String[] amendedArgs = new String[args.length + 2]; amendedArgs[0] = "-cp"; amendedArgs[1] = systemServerClasspath; - System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length); + System.arraycopy(args, 0, amendedArgs, 2, args.length); + args = amendedArgs; } WrapperInit.execApplication(parsedArgs.invokeWith, @@ -477,8 +478,7 @@ public class ZygoteInit { } else { ClassLoader cl = null; if (systemServerClasspath != null) { - cl = createSystemServerClassLoader(systemServerClasspath, - parsedArgs.targetSdkVersion); + cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion); Thread.currentThread().setContextClassLoader(cl); } @@ -493,15 +493,14 @@ public class ZygoteInit { } /** - * Creates a PathClassLoader for the system server. It also creates - * a shared namespace associated with the classloader to let it access - * platform-private native libraries. + * Creates a PathClassLoader for the given class path that is associated with a shared + * namespace, i.e., this classloader can access platform-private native libraries. The + * classloader will use java.library.path as the native library path. */ - private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath, - int targetSdkVersion) { + static PathClassLoader createPathClassLoader(String classPath, int targetSdkVersion) { String libraryPath = System.getProperty("java.library.path"); - return PathClassLoaderFactory.createClassLoader(systemServerClasspath, + return PathClassLoaderFactory.createClassLoader(classPath, libraryPath, libraryPath, ClassLoader.getSystemClassLoader(), diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index c991f22b6294..58e4051b5111 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3593,7 +3593,7 @@ android:permission="android.permission.BIND_JOB_SERVICE" > </service> - <service android:name="com.android.server.BackgroundDexOptJobService" + <service android:name="com.android.server.pm.BackgroundDexOptService" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE"> </service> diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk index fba8e2300607..dbc9e5d55e37 100644 --- a/core/tests/coretests/Android.mk +++ b/core/tests/coretests/Android.mk @@ -40,6 +40,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy LOCAL_PACKAGE_NAME := FrameworksCoreTests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java index 704f0ce7624b..5973d3e33323 100644 --- a/drm/java/android/drm/DrmManagerClient.java +++ b/drm/java/android/drm/DrmManagerClient.java @@ -275,6 +275,10 @@ public class DrmManagerClient implements AutoCloseable { * the {@link DrmManagerClient} object is no longer needed in your * application. After this method is called, {@link DrmManagerClient} is no * longer usable since it has lost all of its required resource. + * + * This method was added in API 24. In API versions 16 through 23, release() + * should be called instead. There is no need to do anything for API + * versions prior to 16. */ @Override public void close() { diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 95577caf65a8..341640146d02 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -24,6 +24,7 @@ import static android.content.res.FontResourcesParser.FamilyResourceEntry; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.content.res.AssetManager; import android.graphics.fonts.FontRequest; import android.graphics.fonts.FontResult; @@ -88,7 +89,7 @@ public class Typeface { @GuardedBy("sLock") private static FontsContract sFontsContract; @GuardedBy("sLock") - private static Handler mHandler; + private static Handler sHandler; /** * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16. @@ -226,6 +227,20 @@ public class Typeface { } /** + * Set the application context so we can generate font requests from the provider. This should + * be called from ActivityThread when the application binds, as we preload fonts. + * @hide + */ + public static void setApplicationContext(Context context) { + synchronized (sLock) { + if (sFontsContract == null) { + sFontsContract = new FontsContract(context); + sHandler = new Handler(); + } + } + } + + /** * Create a typeface object given a font request. The font will be asynchronously fetched, * therefore the result is delivered to the given callback. See {@link FontRequest}. * Only one of the methods in callback will be invoked, depending on whether the request @@ -241,18 +256,17 @@ public class Typeface { Typeface cachedTypeface = findFromCache( request.getProviderAuthority(), request.getQuery()); if (cachedTypeface != null) { - mHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface)); + sHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface)); return; } synchronized (sLock) { if (sFontsContract == null) { - sFontsContract = new FontsContract(); - mHandler = new Handler(); + throw new RuntimeException("Context not initialized, can't query provider"); } final ResultReceiver receiver = new ResultReceiver(null) { @Override public void onReceiveResult(int resultCode, Bundle resultData) { - mHandler.post(() -> receiveResult(request, callback, resultCode, resultData)); + sHandler.post(() -> receiveResult(request, callback, resultCode, resultData)); } }; sFontsContract.getFont(request, receiver); diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 40ab7788f218..3f842e0b5679 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -190,7 +190,7 @@ const char* gFS_Transfer_Functions = R"__SHADER__( // Dithering must be done in the quantization space // When we are writing to an sRGB framebuffer, we must do the following: // EOTF(OETF(color) + dither) -// The dithering pattern is generated with a triangle noise generator in the range [-0.0,1.0] +// The dithering pattern is generated with a triangle noise generator in the range [-1.0,1.0] // TODO: Handle linear fp16 render targets const char* gFS_Gradient_Functions = R"__SHADER__( float triangleNoise(const highp vec2 n) { @@ -203,7 +203,7 @@ const char* gFS_Gradient_Functions = R"__SHADER__( const char* gFS_Gradient_Preamble[2] = { // Linear framebuffer "\nvec4 dither(const vec4 color) {\n" - " return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);\n" + " return color + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);\n" "}\n" "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n" " vec4 c = mix(a, b, v);\n" diff --git a/packages/MtpDocumentsProvider/tests/Android.mk b/packages/MtpDocumentsProvider/tests/Android.mk index e50d6fb693c9..148cd0d930ab 100644 --- a/packages/MtpDocumentsProvider/tests/Android.mk +++ b/packages/MtpDocumentsProvider/tests/Android.mk @@ -8,5 +8,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test LOCAL_PACKAGE_NAME := MtpDocumentsProviderTests LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider LOCAL_CERTIFICATE := media +LOCAL_COMPATIBILITY_SUITE := device-tests include $(BUILD_PACKAGE) diff --git a/packages/PrintSpooler/tests/outofprocess/Android.mk b/packages/PrintSpooler/tests/outofprocess/Android.mk index d1d0ee40ba01..3c02453c78a1 100644 --- a/packages/PrintSpooler/tests/outofprocess/Android.mk +++ b/packages/PrintSpooler/tests/outofprocess/Android.mk @@ -24,5 +24,6 @@ LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4 LOCAL_PACKAGE_NAME := PrintSpoolerOutOfProcessTests +LOCAL_COMPATIBILITY_SUITE := device-tests include $(BUILD_PACKAGE) diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk index 60d1c770d0de..7ace048324c3 100644 --- a/packages/SettingsLib/tests/integ/Android.mk +++ b/packages/SettingsLib/tests/integ/Android.mk @@ -25,6 +25,7 @@ LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common LOCAL_JACK_FLAGS := --multi-dex native LOCAL_PACKAGE_NAME := SettingsLibTests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_STATIC_JAVA_LIBRARIES := \ android-support-test \ diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk index acd552da6081..48b757c30cd1 100644 --- a/packages/Shell/tests/Android.mk +++ b/packages/Shell/tests/Android.mk @@ -16,6 +16,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ legacy-android-test \ LOCAL_PACKAGE_NAME := ShellTests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_INSTRUMENTATION_FOR := Shell LOCAL_CERTIFICATE := platform diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index c0fb4d5e956c..198cb9e7689f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -41,10 +41,10 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS; -import com.android.systemui.qs.QSDetailClipper; import com.android.systemui.plugins.qs.QSTile; -import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; +import com.android.systemui.qs.QSDetailClipper; import com.android.systemui.qs.QSTileHost; +import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; import com.android.systemui.statusbar.policy.KeyguardMonitor; import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback; @@ -74,6 +74,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene private boolean mFinishedFetchingTiles = false; private int mX; private int mY; + private boolean mOpening; public QSCustomizer(Context context, AttributeSet attrs) { super(new ContextThemeWrapper(context, R.style.edit_theme), attrs); @@ -140,6 +141,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene mY = y; MetricsLogger.visible(getContext(), MetricsProto.MetricsEvent.QS_EDIT); isShown = true; + mOpening = true; setTileSpecs(); setVisibility(View.VISIBLE); mClipper.animateCircularClip(x, y, true, mExpandAnimationListener); @@ -226,7 +228,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene } private final Callback mKeyguardCallback = () -> { - if (Dependency.get(KeyguardMonitor.class).isShowing()) { + if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) { hide(0, 0); } }; @@ -237,11 +239,13 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene if (isShown) { setCustomizing(true); } + mOpening = false; mNotifQsContainer.setCustomizerAnimating(false); } @Override public void onAnimationCancel(Animator animation) { + mOpening = false; mNotifQsContainer.setCustomizerAnimating(false); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java index af464c6d138f..5db5498e9bb6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java @@ -136,12 +136,7 @@ public class NotificationInfo extends LinearLayout implements GutsContent { if (channel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) { channelNameText = mContext.getString(R.string.notification_header_default_channel); } else { - if (info != null && channel.getNameResId() != 0) { - channelNameText = pm.getText(pkg, channel.getNameResId(), info); - } - if (channel.getName() != null) { - channelNameText = channel.getName(); - } + channelNameText = channel.getName(); } ((TextView) findViewById(R.id.pkgname)).setText(appName); ((TextView) findViewById(R.id.channel_name)).setText(channelNameText); @@ -154,12 +149,7 @@ public class NotificationInfo extends LinearLayout implements GutsContent { iNotificationManager.getNotificationChannelGroupForPackage( channel.getGroup(), pkg, appUid); if (notificationChannelGroup != null) { - if (info != null && notificationChannelGroup.getNameResId() != 0) { - groupName = pm.getText(pkg, notificationChannelGroup.getNameResId(), info); - } - if (notificationChannelGroup.getName() != null) { - groupName = notificationChannelGroup.getName(); - } + groupName = notificationChannelGroup.getName(); } } catch (RemoteException e) { Log.e(TAG, e.toString()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java index a87b50a4a8df..d6c080ad1f44 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java @@ -129,6 +129,7 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback public void notifyKeyguardDoneFading() { mKeyguardFadingAway = false; + mKeyguardGoingAway = false; notifyKeyguardChanged(); } diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java index 5df3beb471b5..cd85a760159b 100644 --- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java +++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java @@ -38,19 +38,19 @@ public class NotificationChannels extends SystemUI { nm.createNotificationChannels(Arrays.asList( new NotificationChannel( ALERTS, - R.string.notification_channel_alerts, + context.getString(R.string.notification_channel_alerts), NotificationManager.IMPORTANCE_HIGH), new NotificationChannel( SCREENSHOTS, - R.string.notification_channel_screenshot, + context.getString(R.string.notification_channel_screenshot), NotificationManager.IMPORTANCE_LOW), new NotificationChannel( GENERAL, - R.string.notification_channel_general, + context.getString(R.string.notification_channel_general), NotificationManager.IMPORTANCE_MIN), new NotificationChannel( STORAGE, - R.string.notification_channel_storage, + context.getString(R.string.notification_channel_storage), isTv(context) ? NotificationManager.IMPORTANCE_DEFAULT : NotificationManager.IMPORTANCE_LOW) diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index 576299fe0057..10ff8adc3180 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -26,6 +26,7 @@ LOCAL_PROTOC_FLAGS := -I$(LOCAL_PATH)/.. LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors LOCAL_PACKAGE_NAME := SystemUITests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_SRC_FILES := $(call all-java-files-under, src) \ $(call all-Iaidl-files-under, src) \ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java index 5b9270d4e4ed..726300f79fc1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java @@ -161,27 +161,6 @@ public class NotificationInfoTest extends SysuiTestCase { } @Test - public void testBindNotification_SetsGroupName_resId() throws Exception { - when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME), - eq(R.string.legacy_vpn_name), anyObject())).thenReturn( - getContext().getString(R.string.legacy_vpn_name)); - mNotificationChannel.setGroup("test_group_id"); - final NotificationChannelGroup notificationChannelGroup = - new NotificationChannelGroup("test_group_id", R.string.legacy_vpn_name); - when(mMockINotificationManager.getNotificationChannelGroupForPackage( - eq("test_group_id"), eq(TEST_PACKAGE_NAME), anyInt())) - .thenReturn(notificationChannelGroup); - mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, - mMockStatusBarNotification, mNotificationChannel, null, null, null); - final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name); - assertEquals(View.VISIBLE, groupNameView.getVisibility()); - assertEquals(mContext.getString(R.string.legacy_vpn_name), groupNameView.getText()); - final TextView groupDividerView = - (TextView) mNotificationInfo.findViewById(R.id.pkg_group_divider); - assertEquals(View.VISIBLE, groupDividerView.getVisibility()); - } - - @Test public void testBindNotification_SetsTextChannelName() throws Exception { mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, mMockStatusBarNotification, mNotificationChannel, null, null, null); @@ -190,21 +169,6 @@ public class NotificationInfoTest extends SysuiTestCase { } @Test - public void testBindNotification_SetsTextChannelName_resId() throws Exception { - when(mMockPackageManager.getText(eq(TEST_PACKAGE_NAME), - eq(R.string.notification_menu_accessibility), anyObject())).thenReturn( - getContext().getString(R.string.notification_menu_accessibility)); - NotificationChannel notificationChannelResId = new NotificationChannel( - TEST_CHANNEL, R.string.notification_menu_accessibility, - NotificationManager.IMPORTANCE_LOW); - mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, - mMockStatusBarNotification, notificationChannelResId, null, null, null); - final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); - assertEquals(getContext().getString(R.string.notification_menu_accessibility), - textView.getText()); - } - - @Test public void testBindNotification_SetsOnClickListenerForSettings() throws Exception { final CountDownLatch latch = new CountDownLatch(1); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 3800f297a8cc..0cc2311a8110 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -1180,7 +1180,7 @@ message MetricsEvent { // OS: 6.0 BRIGHTNESS_DIALOG = 220; - // OPEN: Settings > Apps > Configure Apps > Draw over other apps + // OPEN: Settings > Apps > Configure Apps > Display over other apps // CATEGORY: SETTINGS // OS: 6.0 SYSTEM_ALERT_WINDOW_APPS = 221; @@ -3227,7 +3227,7 @@ message MetricsEvent { // ACTION: Allow "Draw over other apps" for an app APP_SPECIAL_PERMISSION_APPDRAW_ALLOW = 770; - // ACTION: Deny "Draw over other apps" for an app + // ACTION: Deny "Display over other apps" for an app APP_SPECIAL_PERMISSION_APPDRAW_DENY = 771; // ACTION: Allow "VR helper services" for an app diff --git a/services/core/java/com/android/server/BackgroundDexOptJobService.java b/services/core/java/com/android/server/BackgroundDexOptJobService.java deleted file mode 100644 index 69e6ac50fa8a..000000000000 --- a/services/core/java/com/android/server/BackgroundDexOptJobService.java +++ /dev/null @@ -1,306 +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.server; - -import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT; - -import android.app.job.JobInfo; -import android.app.job.JobParameters; -import android.app.job.JobScheduler; -import android.app.job.JobService; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.BatteryManager; -import android.os.Environment; -import android.os.ServiceManager; -import android.os.storage.StorageManager; -import android.util.ArraySet; -import android.util.Log; -import com.android.server.pm.PackageManagerService; - -import java.io.File; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.TimeUnit; - -public class BackgroundDexOptJobService extends JobService { - private static final String TAG = "BackgroundDexOptJobService"; - - private static final boolean DEBUG = false; - - private static final int JOB_IDLE_OPTIMIZE = 800; - private static final int JOB_POST_BOOT_UPDATE = 801; - - private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG - ? TimeUnit.MINUTES.toMillis(1) - : TimeUnit.DAYS.toMillis(1); - - private static ComponentName sDexoptServiceName = new ComponentName( - "android", - BackgroundDexOptJobService.class.getName()); - - /** - * Set of failed packages remembered across job runs. - */ - static final ArraySet<String> sFailedPackageNames = new ArraySet<String>(); - - /** - * Atomics set to true if the JobScheduler requests an abort. - */ - final AtomicBoolean mAbortPostBootUpdate = new AtomicBoolean(false); - final AtomicBoolean mAbortIdleOptimization = new AtomicBoolean(false); - - /** - * Atomic set to true if one job should exit early because another job was started. - */ - final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false); - - private final File mDataDir = Environment.getDataDirectory(); - - public static void schedule(Context context) { - JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); - - // Schedule a one-off job which scans installed packages and updates - // out-of-date oat files. - js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName) - .setMinimumLatency(TimeUnit.MINUTES.toMillis(1)) - .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1)) - .build()); - - // Schedule a daily job which scans installed packages and compiles - // those with fresh profiling data. - js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName) - .setRequiresDeviceIdle(true) - .setRequiresCharging(true) - .setPeriodic(IDLE_OPTIMIZATION_PERIOD) - .build()); - - if (DEBUG_DEXOPT) { - Log.i(TAG, "Jobs scheduled"); - } - } - - public static void notifyPackageChanged(String packageName) { - // The idle maintanance job skips packages which previously failed to - // compile. The given package has changed and may successfully compile - // now. Remove it from the list of known failing packages. - synchronized (sFailedPackageNames) { - sFailedPackageNames.remove(packageName); - } - } - - // Returns the current battery level as a 0-100 integer. - private int getBatteryLevel() { - IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - Intent intent = registerReceiver(null, filter); - int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); - int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); - - if (level < 0 || scale <= 0) { - // Battery data unavailable. This should never happen, so assume the worst. - return 0; - } - - return (100 * level / scale); - } - - private long getLowStorageThreshold() { - @SuppressWarnings("deprecation") - final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir); - if (lowThreshold == 0) { - Log.e(TAG, "Invalid low storage threshold"); - } - - return lowThreshold; - } - - private boolean runPostBootUpdate(final JobParameters jobParams, - final PackageManagerService pm, final ArraySet<String> pkgs) { - if (mExitPostBootUpdate.get()) { - // This job has already been superseded. Do not start it. - return false; - } - new Thread("BackgroundDexOptService_PostBootUpdate") { - @Override - public void run() { - postBootUpdate(jobParams, pm, pkgs); - } - - }.start(); - return true; - } - - private void postBootUpdate(JobParameters jobParams, PackageManagerService pm, - ArraySet<String> pkgs) { - // Load low battery threshold from the system config. This is a 0-100 integer. - final int lowBatteryThreshold = getResources().getInteger( - com.android.internal.R.integer.config_lowBatteryWarningLevel); - final long lowThreshold = getLowStorageThreshold(); - - mAbortPostBootUpdate.set(false); - - for (String pkg : pkgs) { - if (mAbortPostBootUpdate.get()) { - // JobScheduler requested an early abort. - return; - } - if (mExitPostBootUpdate.get()) { - // Different job, which supersedes this one, is running. - break; - } - if (getBatteryLevel() < lowBatteryThreshold) { - // Rather bail than completely drain the battery. - break; - } - long usableSpace = mDataDir.getUsableSpace(); - if (usableSpace < lowThreshold) { - // Rather bail than completely fill up the disk. - Log.w(TAG, "Aborting background dex opt job due to low storage: " + - usableSpace); - break; - } - - if (DEBUG_DEXOPT) { - Log.i(TAG, "Updating package " + pkg); - } - - // Update package if needed. Note that there can be no race between concurrent - // jobs because PackageDexOptimizer.performDexOpt is synchronized. - - // checkProfiles is false to avoid merging profiles during boot which - // might interfere with background compilation (b/28612421). - // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will - // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a - // trade-off worth doing to save boot time work. - pm.performDexOpt(pkg, - /* checkProfiles */ false, - PackageManagerService.REASON_BOOT, - /* force */ false); - } - // Ran to completion, so we abandon our timeslice and do not reschedule. - jobFinished(jobParams, /* reschedule */ false); - } - - private boolean runIdleOptimization(final JobParameters jobParams, - final PackageManagerService pm, final ArraySet<String> pkgs) { - new Thread("BackgroundDexOptService_IdleOptimization") { - @Override - public void run() { - idleOptimization(jobParams, pm, pkgs); - } - }.start(); - return true; - } - - private void idleOptimization(JobParameters jobParams, PackageManagerService pm, - ArraySet<String> pkgs) { - Log.i(TAG, "Performing idle optimizations"); - // If post-boot update is still running, request that it exits early. - mExitPostBootUpdate.set(true); - - mAbortIdleOptimization.set(false); - - final long lowThreshold = getLowStorageThreshold(); - for (String pkg : pkgs) { - if (mAbortIdleOptimization.get()) { - // JobScheduler requested an early abort. - return; - } - - synchronized (sFailedPackageNames) { - if (sFailedPackageNames.contains(pkg)) { - // Skip previously failing package - continue; - } - } - - long usableSpace = mDataDir.getUsableSpace(); - if (usableSpace < lowThreshold) { - // Rather bail than completely fill up the disk. - Log.w(TAG, "Aborting background dex opt job due to low storage: " + - usableSpace); - break; - } - - // Conservatively add package to the list of failing ones in case performDexOpt - // never returns. - synchronized (sFailedPackageNames) { - sFailedPackageNames.add(pkg); - } - // Optimize package if needed. Note that there can be no race between - // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized. - if (pm.performDexOpt(pkg, - /* checkProfiles */ true, - PackageManagerService.REASON_BACKGROUND_DEXOPT, - /* force */ false)) { - // Dexopt succeeded, remove package from the list of failing ones. - synchronized (sFailedPackageNames) { - sFailedPackageNames.remove(pkg); - } - } - } - // Ran to completion, so we abandon our timeslice and do not reschedule. - jobFinished(jobParams, /* reschedule */ false); - } - - @Override - public boolean onStartJob(JobParameters params) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "onStartJob"); - } - - // NOTE: PackageManagerService.isStorageLow uses a different set of criteria from - // the checks above. This check is not "live" - the value is determined by a background - // restart with a period of ~1 minute. - PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package"); - if (pm.isStorageLow()) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Low storage, skipping this run"); - } - return false; - } - - final ArraySet<String> pkgs = pm.getOptimizablePackages(); - if (pkgs == null || pkgs.isEmpty()) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "No packages to optimize"); - } - return false; - } - - if (params.getJobId() == JOB_POST_BOOT_UPDATE) { - return runPostBootUpdate(params, pm, pkgs); - } else { - return runIdleOptimization(params, pm, pkgs); - } - } - - @Override - public boolean onStopJob(JobParameters params) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "onStopJob"); - } - - if (params.getJobId() == JOB_POST_BOOT_UPDATE) { - mAbortPostBootUpdate.set(true); - } else { - mAbortIdleOptimization.set(true); - } - return false; - } -} diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index bcee2c1bd9ea..34c73d2e2e4e 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -146,6 +146,7 @@ public class LockSettingsService extends ILockSettings.Stub { private final LockPatternUtils mLockPatternUtils; private final NotificationManager mNotificationManager; private final UserManager mUserManager; + private final DevicePolicyManager mDevicePolicyManager; private final IActivityManager mActivityManager; private final KeyStore mKeyStore; @@ -333,6 +334,10 @@ public class LockSettingsService extends ILockSettings.Stub { return (UserManager) mContext.getSystemService(Context.USER_SERVICE); } + public DevicePolicyManager getDevicePolicyManager() { + return (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); + } + public KeyStore getKeyStore() { return KeyStore.getInstance(); } @@ -380,6 +385,7 @@ public class LockSettingsService extends ILockSettings.Stub { mStorage = injector.getStorage(); mNotificationManager = injector.getNotificationManager(); mUserManager = injector.getUserManager(); + mDevicePolicyManager = injector.getDevicePolicyManager(); mStrongAuthTracker = injector.getStrongAuthTracker(); mStrongAuthTracker.register(mStrongAuth); @@ -2015,14 +2021,17 @@ public class LockSettingsService extends ILockSettings.Stub { } } long handle = getSyntheticPasswordHandleLocked(userId); - AuthenticationToken auth = mSpManager.unwrapPasswordBasedSyntheticPassword( - getGateKeeperService(), handle, savedCredential, userId).authToken; + AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( + getGateKeeperService(), handle, savedCredential, userId); + VerifyCredentialResponse response = authResult.gkResponse; + AuthenticationToken auth = authResult.authToken; if (auth != null) { // We are performing a trusted credential change i.e. a correct existing credential // is provided setLockCredentialWithAuthTokenLocked(credential, credentialType, auth, userId); mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId); - } else { + } else if (response != null + && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR){ // We are performing an untrusted credential change i.e. by DevicePolicyManager. // So provision a new SP and SID. This would invalidate existing escrow tokens. // Still support this for now but this flow will be removed in the next release. @@ -2031,6 +2040,10 @@ public class LockSettingsService extends ILockSettings.Stub { initializeSyntheticPasswordLocked(null, credential, credentialType, userId); synchronizeUnifiedWorkChallengeForProfiles(userId, null); mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId); + } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ { + Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " + + (response != null ? "rate limit exceeded" : "failed")); + return; } notifyActivePasswordMetricsAvailable(credential, userId); @@ -2042,7 +2055,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId); synchronized (mSpManager) { enableSyntheticPasswordLocked(); - // Migrate to synthetic password based credentials if ther user has no password, + // Migrate to synthetic password based credentials if the user has no password, // the token can then be activated immediately. AuthenticationToken auth = null; if (!isUserSecure(userId)) { @@ -2201,22 +2214,20 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.i(TAG, "Managed profile can have escrow token"); return; } - DevicePolicyManager dpm = (DevicePolicyManager) - mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); // Devices with Device Owner should have escrow enabled on all users. - if (dpm.getDeviceOwnerComponentOnAnyUser() != null) { + if (mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser() != null) { Slog.i(TAG, "Corp-owned device can have escrow token"); return; } // We could also have a profile owner on the given (non-managed) user for unicorn cases - if (dpm.getProfileOwnerAsUser(userId) != null) { + if (mDevicePolicyManager.getProfileOwnerAsUser(userId) != null) { Slog.i(TAG, "User with profile owner can have escrow token"); return; } // If the device is yet to be provisioned (still in SUW), there is still // a chance that Device Owner will be set on the device later, so postpone // disabling escrow token for now. - if (!dpm.isDeviceProvisioned()) { + if (!mDevicePolicyManager.isDeviceProvisioned()) { Slog.i(TAG, "Postpone disabling escrow tokens until device is provisioned"); return; } diff --git a/services/core/java/com/android/server/SyntheticPasswordManager.java b/services/core/java/com/android/server/SyntheticPasswordManager.java index 62678801a9a2..2517613c03e0 100644 --- a/services/core/java/com/android/server/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/SyntheticPasswordManager.java @@ -526,7 +526,7 @@ public class SyntheticPasswordManager { * RESPONSE_OK, since user authentication failures are detected earlier when trying to * decrypt SP. */ - public VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper, + public @Nullable VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper, @NonNull AuthenticationToken auth, long challenge, int userId) throws RemoteException { byte[] spHandle = loadSyntheticPasswordHandle(userId); if (spHandle == null) { diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index ebbce0227b3e..918747b37076 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -251,7 +251,8 @@ class ActivityMetricsLogger { * ActivityManagerInternal.APP_TRANSITION_* reasons. */ void notifyTransitionStarting(SparseIntArray stackIdReasons) { - if (!isAnyTransitionActive() || mLoggedTransitionStarting) { + // TODO (b/36339388): Figure out why stackIdReasons can be null + if (stackIdReasons == null || !isAnyTransitionActive() || mLoggedTransitionStarting) { return; } mCurrentTransitionDelayMs = calculateCurrentDelay(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index be8aaf02db41..82809469d89c 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -159,6 +159,8 @@ import com.android.server.notification.ManagedServices.UserProfiles; import libcore.io.IoUtils; +import com.google.android.collect.Lists; + import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; @@ -1658,8 +1660,7 @@ public class NotificationManagerService extends SystemService { public NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, boolean includeDeleted) { checkCallerIsSystem(); - return mRankingHelper.getNotificationChannel - (pkg, uid, channelId, includeDeleted); + return mRankingHelper.getNotificationChannel(pkg, uid, channelId, includeDeleted); } @Override @@ -1675,6 +1676,27 @@ public class NotificationManagerService extends SystemService { } @Override + public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups( + String pkg) { + checkCallerIsSystemOrSameApp(pkg); + return new ParceledListSlice<>(new ArrayList( + mRankingHelper.getNotificationChannelGroups(pkg, Binder.getCallingUid()))); + } + + @Override + public void deleteNotificationChannelGroup(String pkg, String channelGroupId) { + checkCallerIsSystemOrSameApp(pkg); + + List<String> deletedChannelIds = mRankingHelper.deleteNotificationChannelGroup( + pkg, Binder.getCallingUid(), channelGroupId); + for (int i = 0; i < deletedChannelIds.size(); i++) { + cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannelIds.get(i), 0, 0, true, + UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null); + } + savePolicyFile(); + } + + @Override public void updateNotificationChannelForPackage(String pkg, int uid, NotificationChannel channel) { enforceSystemOrSystemUI("Caller not system or systemui"); @@ -1698,6 +1720,12 @@ public class NotificationManagerService extends SystemService { } @Override + public int getDeletedChannelCount(String pkg, int uid) { + enforceSystemOrSystemUI("getDeletedChannelCount"); + return mRankingHelper.getDeletedChannelCount(pkg, uid); + } + + @Override public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage( String pkg, int uid, boolean includeDeleted) { checkCallerIsSystem(); diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 4b1804c8e7a7..02f92fedb85d 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -15,8 +15,6 @@ */ package com.android.server.notification; -import static android.app.NotificationManager.IMPORTANCE_NONE; - import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; @@ -69,7 +67,6 @@ public class RankingHelper implements RankingConfig { private static final String ATT_VERSION = "version"; private static final String ATT_NAME = "name"; - private static final String ATT_NAME_RES_ID = "name_res_id"; private static final String ATT_UID = "uid"; private static final String ATT_ID = "id"; private static final String ATT_PRIORITY = "priority"; @@ -195,14 +192,9 @@ public class RankingHelper implements RankingConfig { if (TAG_GROUP.equals(tagName)) { String id = parser.getAttributeValue(null, ATT_ID); CharSequence groupName = parser.getAttributeValue(null, ATT_NAME); - int groupNameRes = safeInt(parser, ATT_NAME_RES_ID, 0); if (!TextUtils.isEmpty(id)) { - NotificationChannelGroup group = null; - if (groupName != null) { - group = new NotificationChannelGroup(id, groupName); - } else { - group = new NotificationChannelGroup(id, groupNameRes); - } + NotificationChannelGroup group + = new NotificationChannelGroup(id, groupName); r.groups.put(id, group); } } @@ -210,19 +202,12 @@ public class RankingHelper implements RankingConfig { if (TAG_CHANNEL.equals(tagName)) { String id = parser.getAttributeValue(null, ATT_ID); CharSequence channelName = parser.getAttributeValue(null, ATT_NAME); - int channelNameRes = safeInt(parser, ATT_NAME_RES_ID, 0); int channelImportance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE); - if (!TextUtils.isEmpty(id)) { - NotificationChannel channel; - if (channelName != null) { - channel = new NotificationChannel(id, channelName, - channelImportance); - } else { - channel = new NotificationChannel(id, channelNameRes, - channelImportance); - } + if (!TextUtils.isEmpty(id) && !TextUtils.isEmpty(channelName)) { + NotificationChannel channel = new NotificationChannel(id, + channelName, channelImportance); channel.populateFromXml(parser); r.channels.put(id, channel); } @@ -302,7 +287,7 @@ public class RankingHelper implements RankingConfig { NotificationChannel channel; channel = new NotificationChannel( NotificationChannel.DEFAULT_CHANNEL_ID, - R.string.default_notification_channel_label, + mContext.getString(R.string.default_notification_channel_label), r.importance); channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX); channel.setLockscreenVisibility(r.visibility); @@ -482,8 +467,7 @@ public class RankingHelper implements RankingConfig { Preconditions.checkNotNull(pkg); Preconditions.checkNotNull(group); Preconditions.checkNotNull(group.getId()); - Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()) - || group.getNameResId() != 0); + Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName())); Record r = getOrCreateRecord(pkg, uid); if (r == null) { throw new IllegalArgumentException("Invalid package"); @@ -504,8 +488,7 @@ public class RankingHelper implements RankingConfig { Preconditions.checkNotNull(pkg); Preconditions.checkNotNull(channel); Preconditions.checkNotNull(channel.getId()); - Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()) - || channel.getNameResId() != 0); + Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName())); Record r = getOrCreateRecord(pkg, uid); if (r == null) { throw new IllegalArgumentException("Invalid package"); @@ -524,7 +507,7 @@ public class RankingHelper implements RankingConfig { existing.setDeleted(false); } - existing.setNameResId(channel.getNameResId()); + existing.setName(channel.getName()); MetricsLogger.action(getChannelLog(channel, pkg)); updateConfig(); @@ -669,8 +652,6 @@ public class RankingHelper implements RankingConfig { @Override public void deleteNotificationChannel(String pkg, int uid, String channelId) { - Preconditions.checkNotNull(pkg); - Preconditions.checkNotNull(channelId); Record r = getRecord(pkg, uid); if (r == null) { return; @@ -682,6 +663,7 @@ public class RankingHelper implements RankingConfig { LogMaker lm = getChannelLog(channel, pkg); lm.setType(MetricsProto.MetricsEvent.TYPE_CLOSE); MetricsLogger.action(lm); + updateConfig(); } @Override @@ -694,6 +676,7 @@ public class RankingHelper implements RankingConfig { return; } r.channels.remove(channelId); + updateConfig(); } @Override @@ -710,6 +693,7 @@ public class RankingHelper implements RankingConfig { r.channels.remove(key); } } + updateConfig(); } public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg, @@ -734,12 +718,15 @@ public class RankingHelper implements RankingConfig { final NotificationChannel nc = r.channels.valueAt(i); if (includeDeleted || !nc.isDeleted()) { if (nc.getGroup() != null) { - NotificationChannelGroup ncg = groups.get(nc.getGroup()); - if (ncg == null ) { - ncg = r.groups.get(nc.getGroup()).clone(); - groups.put(nc.getGroup(), ncg); + if (r.groups.get(nc.getGroup()) != null) { + NotificationChannelGroup ncg = groups.get(nc.getGroup()); + if (ncg == null) { + ncg = r.groups.get(nc.getGroup()).clone(); + groups.put(nc.getGroup(), ncg); + + } + ncg.addChannel(nc); } - ncg.addChannel(nc); } else { nonGrouped.addChannel(nc); } @@ -751,8 +738,29 @@ public class RankingHelper implements RankingConfig { return new ParceledListSlice<>(new ArrayList<>(groups.values())); } + public List<String> deleteNotificationChannelGroup(String pkg, int uid, + String groupId) { + List<String> deletedChannelIds = new ArrayList<>(); + Record r = getRecord(pkg, uid); + if (r == null || TextUtils.isEmpty(groupId)) { + return deletedChannelIds; + } + + r.groups.remove(groupId); + + int N = r.channels.size(); + for (int i = 0; i < N; i++) { + final NotificationChannel nc = r.channels.valueAt(i); + if (groupId.equals(nc.getGroup())) { + nc.setDeleted(true); + deletedChannelIds.add(nc.getId()); + } + } + updateConfig(); + return deletedChannelIds; + } + @Override - @VisibleForTesting public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg, int uid) { Record r = getRecord(pkg, uid); @@ -781,6 +789,23 @@ public class RankingHelper implements RankingConfig { return new ParceledListSlice<>(channels); } + public int getDeletedChannelCount(String pkg, int uid) { + Preconditions.checkNotNull(pkg); + int deletedCount = 0; + Record r = getRecord(pkg, uid); + if (r == null) { + return deletedCount; + } + int N = r.channels.size(); + for (int i = 0; i < N; i++) { + final NotificationChannel nc = r.channels.valueAt(i); + if (nc.isDeleted()) { + deletedCount++; + } + } + return deletedCount; + } + /** * Sets importance. */ diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 7aa96cfddc62..d8900c0546fd 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -49,8 +49,6 @@ public class BackgroundDexOptService extends JobService { private static final boolean DEBUG = false; - private static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR; - private static final int JOB_IDLE_OPTIMIZE = 800; private static final int JOB_POST_BOOT_UPDATE = 801; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4ac1cce91402..4640d2018608 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -260,7 +260,6 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.server.AttributeCache; -import com.android.server.BackgroundDexOptJobService; import com.android.server.DeviceIdleController; import com.android.server.EventLogTags; import com.android.server.FgThread; @@ -272,6 +271,7 @@ import com.android.server.SystemConfig; import com.android.server.SystemServerInitThreadPool; import com.android.server.Watchdog; import com.android.server.net.NetworkPolicyManagerInternal; +import com.android.server.pm.BackgroundDexOptService; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.PermissionsState.PermissionState; import com.android.server.pm.Settings.DatabaseVersion; @@ -16850,11 +16850,11 @@ public class PackageManagerService extends IPackageManager.Stub { mDexManager.isUsedByOtherApps(pkg.packageName)); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - // Notify BackgroundDexOptJobService that the package has been changed. + // Notify BackgroundDexOptService that the package has been changed. // If this is an update of a package which used to fail to compile, // BDOS will remove it from its blacklist. // TODO: Layering violation - BackgroundDexOptJobService.notifyPackageChanged(pkg.packageName); + BackgroundDexOptService.notifyPackageChanged(pkg.packageName); } if (!args.doRename(res.returnCode, pkg, oldCodePath)) { diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 2f221df182c0..c20ee973bac5 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -163,9 +163,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree private boolean mLastContainsShowWhenLockedWindow; private boolean mLastContainsDismissKeyguardWindow; - private ArrayList<WindowSurfaceController.SurfaceControlWithBackground> mSurfaceViewBackgrounds = - new ArrayList<>(); - ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>(); @@ -970,36 +967,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mService.mWindowPlacerLocked.performSurfacePlacement(); } - void addSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) { - mSurfaceViewBackgrounds.add(background); - } - - void removeSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) { - mSurfaceViewBackgrounds.remove(background); - updateSurfaceViewBackgroundVisibilities(); - } - - // We use DimLayers behind SurfaceViews to prevent holes while resizing and creating. - // However, we need to ensure one SurfaceView doesn't cover another when they are both placed - // below the main app window (as traditionally a SurfaceView which is never drawn - // to is totally translucent). So we look at all our SurfaceView backgrounds and only enable - // the background for the SurfaceView with lowest Z order - void updateSurfaceViewBackgroundVisibilities() { - WindowSurfaceController.SurfaceControlWithBackground bottom = null; - int bottomLayer = Integer.MAX_VALUE; - for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) { - WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i); - if (sc.mVisible && sc.mLayer < bottomLayer) { - bottomLayer = sc.mLayer; - bottom = sc; - } - } - for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) { - WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i); - sc.updateBackgroundVisibility(sc != bottom); - } - } - void resetJustMovedInStack() { for (int i = mChildren.size() - 1; i >= 0; i--) { (mChildren.get(i)).resetJustMovedInStack(); diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index b7a9e663ab0f..4df513eb27f4 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -208,13 +208,6 @@ public class Session extends IWindowSession.Stub } @Override - public void repositionChild(IWindow window, int left, int top, int right, int bottom, - long deferTransactionUntilFrame, Rect outFrame) { - mService.repositionChild(this, window, left, top, right, bottom, - deferTransactionUntilFrame, outFrame); - } - - @Override public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) { mService.setWillReplaceWindows(appToken, childrenOnly); } @@ -235,10 +228,6 @@ public class Session extends IWindowSession.Stub return res; } - public void performDeferredDestroy(IWindow window) { - mService.performDeferredDestroyWindow(this, window); - } - public boolean outOfMemory(IWindow window) { return mService.outOfMemoryWindow(this, window); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 014a89dd25d7..5551afec76e8 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1808,64 +1808,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - void repositionChild(Session session, IWindow client, - int left, int top, int right, int bottom, - long frameNumber, Rect outFrame) { - Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild"); - long origId = Binder.clearCallingIdentity(); - - try { - synchronized(mWindowMap) { - WindowState win = windowForClientLocked(session, client, false); - if (win == null) { - return; - } - if (!win.isChildWindow()) { - throw new IllegalArgumentException( - "repositionChild called but window is not" - + "attached to a parent win=" + win); - } - - win.mAttrs.x = left; - win.mAttrs.y = top; - win.mAttrs.width = right - left; - win.mAttrs.height = bottom - top; - win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight); - - if (win.mHasSurface) { - if (SHOW_TRANSACTIONS) { - Slog.i(TAG_WM, ">>> OPEN TRANSACTION repositionChild"); - } - - openSurfaceTransaction(); - - try { - - win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame); - win.mWinAnimator.computeShownFrameLocked(); - - win.mWinAnimator.setSurfaceBoundariesLocked(false); - - if (frameNumber > 0) { - win.mWinAnimator.deferTransactionUntilParentFrame(frameNumber); - } - - } finally { - closeSurfaceTransaction(); - if (SHOW_TRANSACTIONS) { - Slog.i(TAG_WM, "<<< CLOSE TRANSACTION repositionChild"); - } - } - } - - outFrame = win.mCompatFrame; - } - } finally { - Binder.restoreCallingIdentity(origId); - Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); - } - } - public int relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, @@ -2210,23 +2152,6 @@ public class WindowManagerService extends IWindowManager.Stub return result; } - public void performDeferredDestroyWindow(Session session, IWindow client) { - long origId = Binder.clearCallingIdentity(); - - try { - synchronized (mWindowMap) { - WindowState win = windowForClientLocked(session, client, false); - if (win == null || win.mWillReplaceWindow) { - return; - } - - win.mWinAnimator.destroyDeferredSurfaceLocked(); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - public boolean outOfMemoryWindow(Session session, IWindow client) { final long origId = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index c9863c5c335e..b08bb70ca0b9 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -97,13 +97,7 @@ class WindowSurfaceController { mWindowType = windowType; mWindowSession = win.mSession; - // For opaque child windows placed under parent windows, we use a special SurfaceControl - // which mirrors commands to a black-out layer placed one Z-layer below the surface. - // This prevents holes to whatever app/wallpaper is underneath. - if (win.isChildWindow() && win.mSubLayer < 0 && win.mAppToken != null) { - mSurfaceControl = new SurfaceControlWithBackground( - s, name, w, h, format, flags, win.mAppToken, windowType, ownerUid); - } else if (DEBUG_SURFACE_TRACE) { + if (DEBUG_SURFACE_TRACE) { mSurfaceControl = new SurfaceTrace( s, name, w, h, format, flags, windowType, ownerUid); } else { @@ -834,141 +828,4 @@ class WindowSurfaceController { + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")"; } } - - class SurfaceControlWithBackground extends SurfaceControl { - private SurfaceControl mBackgroundControl; - private boolean mOpaque = true; - private boolean mAppForcedInvisible = false; - private AppWindowToken mAppToken; - public boolean mVisible = false; - public int mLayer = -1; - - public SurfaceControlWithBackground(SurfaceSession s, String name, int w, int h, int format, - int flags, AppWindowToken token, int windowType, int ownerUid) - throws OutOfResourcesException { - super(s, name, w, h, format, flags, windowType, ownerUid); - mBackgroundControl = new SurfaceControl(s, name, w, h, - PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM); - mOpaque = (flags & SurfaceControl.OPAQUE) != 0; - mAppToken = token; - - mAppToken.addSurfaceViewBackground(this); - } - - @Override - public void setAlpha(float alpha) { - super.setAlpha(alpha); - mBackgroundControl.setAlpha(alpha); - } - - @Override - public void setLayer(int zorder) { - super.setLayer(zorder); - mBackgroundControl.setLayer(zorder - 1); - if (mLayer != zorder) { - mLayer = zorder; - mAppToken.updateSurfaceViewBackgroundVisibilities(); - } - } - - @Override - public void setPosition(float x, float y) { - super.setPosition(x, y); - mBackgroundControl.setPosition(x, y); - } - - @Override - public void setSize(int w, int h) { - super.setSize(w, h); - mBackgroundControl.setSize(w, h); - } - - @Override - public void setWindowCrop(Rect crop) { - super.setWindowCrop(crop); - mBackgroundControl.setWindowCrop(crop); - } - - @Override - public void setFinalCrop(Rect crop) { - super.setFinalCrop(crop); - mBackgroundControl.setFinalCrop(crop); - } - - @Override - public void setLayerStack(int layerStack) { - super.setLayerStack(layerStack); - mBackgroundControl.setLayerStack(layerStack); - } - - @Override - public void setOpaque(boolean isOpaque) { - super.setOpaque(isOpaque); - mOpaque = isOpaque; - updateBackgroundVisibility(mAppForcedInvisible); - } - - @Override - public void setSecure(boolean isSecure) { - super.setSecure(isSecure); - } - - @Override - public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - super.setMatrix(dsdx, dtdx, dsdy, dtdy); - mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy); - } - - @Override - public void hide() { - super.hide(); - if (mVisible) { - mVisible = false; - mAppToken.updateSurfaceViewBackgroundVisibilities(); - } - } - - @Override - public void show() { - super.show(); - if (!mVisible) { - mVisible = true; - mAppToken.updateSurfaceViewBackgroundVisibilities(); - } - } - - @Override - public void destroy() { - super.destroy(); - mBackgroundControl.destroy(); - mAppToken.removeSurfaceViewBackground(this); - } - - @Override - public void release() { - super.release(); - mBackgroundControl.release(); - } - - @Override - public void setTransparentRegionHint(Region region) { - super.setTransparentRegionHint(region); - mBackgroundControl.setTransparentRegionHint(region); - } - - @Override - public void deferTransactionUntil(IBinder handle, long frame) { - super.deferTransactionUntil(handle, frame); - mBackgroundControl.deferTransactionUntil(handle, frame); - } - - void updateBackgroundVisibility(boolean forcedInvisible) { - mAppForcedInvisible = forcedInvisible; - if (mOpaque && mVisible && !mAppForcedInvisible) { - mBackgroundControl.show(); - } else { - mBackgroundControl.hide(); - } - } - } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a8423e2e8a11..f84bfef530a3 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -86,6 +86,7 @@ import com.android.server.notification.NotificationManagerService; import com.android.server.om.OverlayManagerService; import com.android.server.os.DeviceIdentifiersPolicyService; import com.android.server.os.SchedulingPolicyService; +import com.android.server.pm.BackgroundDexOptService; import com.android.server.pm.Installer; import com.android.server.pm.LauncherAppsService; import com.android.server.pm.OtaDexoptService; @@ -1428,11 +1429,11 @@ public final class SystemServer { traceEnd(); } - traceBeginAndSlog("StartBackgroundDexOptJobService"); + traceBeginAndSlog("StartBackgroundDexOptService"); try { - BackgroundDexOptJobService.schedule(context); + BackgroundDexOptService.schedule(context); } catch (Throwable e) { - reportWtf("starting StartBackgroundDexOptJobService", e); + reportWtf("starting StartBackgroundDexOptService", e); } traceEnd(); diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java index a3b0429bb148..3e3a19b8effd 100644 --- a/services/net/java/android/net/ip/IpManager.java +++ b/services/net/java/android/net/ip/IpManager.java @@ -23,6 +23,7 @@ import android.content.Context; import android.net.apf.ApfCapabilities; import android.net.apf.ApfFilter; import android.net.DhcpResults; +import android.net.INetd; import android.net.InterfaceConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -34,10 +35,12 @@ import android.net.dhcp.DhcpClient; import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpManagerEvent; import android.net.util.MultinetworkPolicyTracker; +import android.net.util.NetdService; import android.os.INetworkManagementService; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.os.SystemClock; import android.text.TextUtils; import android.util.LocalLog; @@ -1027,14 +1030,16 @@ public class IpManager extends StateMachine { private boolean startIPv6() { // Set privacy extensions. + final String PREFER_TEMPADDRS = "2"; try { - mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); + NetdService.run((INetd netd) -> { + netd.setProcSysNet( + INetd.IPV6, INetd.CONF, mInterfaceName, "use_tempaddr", + PREFER_TEMPADDRS); + }); mNwService.enableIpv6(mInterfaceName); - } catch (RemoteException re) { - logError("Unable to change interface settings: %s", re); - return false; - } catch (IllegalStateException ie) { - logError("Unable to change interface settings: %s", ie); + } catch (IllegalStateException|RemoteException|ServiceSpecificException e) { + logError("Unable to change interface settings: %s", e); return false; } diff --git a/services/net/java/android/net/util/NetdService.java b/services/net/java/android/net/util/NetdService.java index 153cb502afca..6e69ff56c723 100644 --- a/services/net/java/android/net/util/NetdService.java +++ b/services/net/java/android/net/util/NetdService.java @@ -17,7 +17,10 @@ package android.net.util; import android.net.INetd; +import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; +import android.os.SystemClock; import android.util.Log; @@ -27,15 +30,24 @@ import android.util.Log; public class NetdService { private static final String TAG = NetdService.class.getSimpleName(); private static final String NETD_SERVICE_NAME = "netd"; + private static final long BASE_TIMEOUT_MS = 100; + private static final long MAX_TIMEOUT_MS = 1000; + /** + * Return an INetd instance, or null if not available. + * * It is the caller's responsibility to check for a null return value * and to handle RemoteException errors from invocations on the returned * interface if, for example, netd dies and is restarted. * + * Returned instances of INetd should not be cached. + * * @return an INetd instance or null. */ public static INetd getInstance() { + // NOTE: ServiceManager does no caching for the netd service, + // because netd is not one of the defined common services. final INetd netdInstance = INetd.Stub.asInterface( ServiceManager.getService(NETD_SERVICE_NAME)); if (netdInstance == null) { @@ -43,4 +55,82 @@ public class NetdService { } return netdInstance; } + + /** + * Blocks for a specified time until an INetd instance is available. + * + * It is the caller's responsibility to handle RemoteException errors + * from invocations on the returned interface if, for example, netd + * dies after this interface was returned. + * + * Returned instances of INetd should not be cached. + * + * Special values of maxTimeoutMs include: 0, meaning try to obtain an + * INetd instance only once, and -1 (or any value less than 0), meaning + * try to obtain an INetd instance indefinitely. + * + * @param maxTimeoutMs the maximum time to spend getting an INetd instance + * @return an INetd instance or null if no instance is available + * within |maxTimeoutMs| milliseconds. + */ + public static INetd get(long maxTimeoutMs) { + if (maxTimeoutMs == 0) return getInstance(); + + final long stop = (maxTimeoutMs > 0) + ? SystemClock.elapsedRealtime() + maxTimeoutMs + : Long.MAX_VALUE; + + long timeoutMs = 0; + while (true) { + final INetd netdInstance = getInstance(); + if (netdInstance != null) { + return netdInstance; + } + + final long remaining = stop - SystemClock.elapsedRealtime(); + if (remaining <= 0) break; + + // No netdInstance was received; sleep and retry. + timeoutMs = Math.min(timeoutMs + BASE_TIMEOUT_MS, MAX_TIMEOUT_MS); + timeoutMs = Math.min(timeoutMs, remaining); + try { + Thread.sleep(timeoutMs); + } catch (InterruptedException e) {} + } + return null; + } + + /** + * Blocks until an INetd instance is available. + * + * It is the caller's responsibility to handle RemoteException errors + * from invocations on the returned interface if, for example, netd + * dies after this interface was returned. + * + * Returned instances of INetd should not be cached. + * + * @return an INetd instance. + */ + public static INetd get() { + return get(-1); + } + + public static interface NetdCommand { + void run(INetd netd) throws RemoteException; + } + + /** + * Blocks until an INetd instance is availabe, and retries until either + * the command succeeds or a runtime exception is thrown. + */ + public static void run(NetdCommand cmd) { + while (true) { + try { + cmd.run(get()); + return; + } catch (RemoteException re) { + Log.e(TAG, "error communicating with netd: " + re); + } + } + } } diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk index de9553a46eef..a5d557048232 100644 --- a/services/tests/notification/Android.mk +++ b/services/tests/notification/Android.mk @@ -30,6 +30,7 @@ LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_JACK_FLAGS := --multi-dex native LOCAL_PACKAGE_NAME := FrameworksNotificationTests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java index 5f215f937a97..27b9a880c4ac 100644 --- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java @@ -203,7 +203,6 @@ public class RankingHelperTest { private void compareChannels(NotificationChannel expected, NotificationChannel actual) { assertEquals(expected.getId(), actual.getId()); assertEquals(expected.getName(), actual.getName()); - assertEquals(expected.getNameResId(), actual.getNameResId()); assertEquals(expected.shouldVibrate(), actual.shouldVibrate()); assertEquals(expected.shouldShowLights(), actual.shouldShowLights()); assertEquals(expected.getImportance(), actual.getImportance()); @@ -219,7 +218,6 @@ public class RankingHelperTest { private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) { assertEquals(expected.getId(), actual.getId()); assertEquals(expected.getName(), actual.getName()); - assertEquals(expected.getNameResId(), actual.getNameResId()); } @Test @@ -274,15 +272,12 @@ public class RankingHelperTest { @Test public void testChannelXml() throws Exception { - int nameResId = 924896; - int groupNameResId = 426272; - - NotificationChannelGroup ncg = new NotificationChannelGroup("1", groupNameResId); + NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); NotificationChannel channel2 = - new NotificationChannel("id2", nameResId, IMPORTANCE_LOW); + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); channel2.enableLights(true); channel2.setBypassDnd(true); @@ -728,6 +723,25 @@ public class RankingHelperTest { } @Test + public void testGetDeletedChannelCount() throws Exception { + NotificationChannel channel = + new NotificationChannel("id2", "name2", IMPORTANCE_LOW); + NotificationChannel channel2 = + new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); + NotificationChannel channel3 = + new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); + mHelper.createNotificationChannel(pkg, uid, channel, true); + mHelper.createNotificationChannel(pkg, uid, channel2, true); + mHelper.createNotificationChannel(pkg, uid, channel3, true); + + mHelper.deleteNotificationChannel(pkg, uid, channel.getId()); + mHelper.deleteNotificationChannel(pkg, uid, channel3.getId()); + + assertEquals(2, mHelper.getDeletedChannelCount(pkg, uid)); + assertEquals(0, mHelper.getDeletedChannelCount(pkg2, uid2)); + } + + @Test public void testUpdateDeletedChannels() throws Exception { NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); @@ -840,6 +854,43 @@ public class RankingHelperTest { } @Test + public void testDeleteGroup() throws Exception { + NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted"); + NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted"); + NotificationChannel nonGroupedNonDeletedChannel = + new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH); + NotificationChannel groupedButNotDeleted = + new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT); + groupedButNotDeleted.setGroup("not"); + NotificationChannel groupedAndDeleted = + new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT); + groupedAndDeleted.setGroup("totally"); + + mHelper.createNotificationChannelGroup(pkg, uid, notDeleted, true); + mHelper.createNotificationChannelGroup(pkg, uid, deleted, true); + mHelper.createNotificationChannel(pkg, uid, nonGroupedNonDeletedChannel, true); + mHelper.createNotificationChannel(pkg, uid, groupedAndDeleted, true); + mHelper.createNotificationChannel(pkg, uid, groupedButNotDeleted, true); + + mHelper.deleteNotificationChannelGroup(pkg, uid, deleted.getId()); + + assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), pkg, uid)); + assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), pkg, uid)); + + assertNull(mHelper.getNotificationChannel(pkg, uid, groupedAndDeleted.getId(), false)); + compareChannels(groupedAndDeleted, + mHelper.getNotificationChannel(pkg, uid, groupedAndDeleted.getId(), true)); + + compareChannels(groupedButNotDeleted, + mHelper.getNotificationChannel(pkg, uid, groupedButNotDeleted.getId(), false)); + compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel( + pkg, uid, nonGroupedNonDeletedChannel.getId(), false)); + + // notDeleted + assertEquals(1, mHelper.getNotificationChannelGroups(pkg, uid).size()); + } + + @Test public void testOnPackageChanged_packageRemoval() throws Exception { // Deleted NotificationChannel channel1 = @@ -875,7 +926,7 @@ public class RankingHelperTest { mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid}); - assertEquals(0, mHelper.getNotificationChannelGroups(pkg, uid, true).getList().size()); + assertEquals(0, mHelper.getNotificationChannelGroups(pkg, uid).size()); } @Test @@ -994,14 +1045,18 @@ public class RankingHelperTest { } @Test - public void testCreateChannel_updateNameResId() throws Exception { - NotificationChannel nc = new NotificationChannel("id", 1, IMPORTANCE_DEFAULT); + public void testCreateChannel_updateName() throws Exception { + NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); mHelper.createNotificationChannel(pkg, uid, nc, true); + NotificationChannel actual = mHelper.getNotificationChannel(pkg, uid, "id", false); + assertEquals("hello", actual.getName()); - nc = new NotificationChannel("id", 2, IMPORTANCE_DEFAULT); + nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); mHelper.createNotificationChannel(pkg, uid, nc, true); - assertEquals(2, mHelper.getNotificationChannel(pkg, uid, "id", false).getNameResId()); + actual = mHelper.getNotificationChannel(pkg, uid, "id", false); + assertEquals("goodbye", actual.getName()); + assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); } @Test diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index 15c61f6f228b..2a8f4a34f158 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -30,6 +30,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_PACKAGE_NAME := FrameworksServicesTests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform diff --git a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java index c6265bc768f3..a2a4019c93ad 100644 --- a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java @@ -25,6 +25,8 @@ import static org.mockito.Mockito.when; import android.app.IActivityManager; import android.app.NotificationManager; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; import android.content.Context; import android.content.pm.UserInfo; import android.database.sqlite.SQLiteDatabase; @@ -76,7 +78,7 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { UserManager mUserManager; MockStorageManager mStorageManager; IActivityManager mActivityManager; - + DevicePolicyManager mDevicePolicyManager; KeyStore mKeyStore; @Override @@ -89,7 +91,9 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { mUserManager = mock(UserManager.class); mStorageManager = new MockStorageManager(); mActivityManager = mock(IActivityManager.class); - mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager); + mDevicePolicyManager = mock(DevicePolicyManager.class); + mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager, + mDevicePolicyManager); mStorage = new LockSettingsStorageTestable(mContext, new File(getContext().getFilesDir(), "locksettings")); File storageDir = mStorage.mStorageDir; @@ -122,6 +126,10 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { }); when(mLockPatternUtils.getLockSettings()).thenReturn(mService); + + // Adding a fake Device Owner app which will enable escrow token support in LSS. + when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn( + new ComponentName("com.dummy.package", ".FakeDeviceOwner")); } @Override diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java index c68fbdc0a2ac..46779048e9db 100644 --- a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java +++ b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.NotificationManager; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.ContextWrapper; import android.content.pm.UserInfo; @@ -68,7 +69,7 @@ public class LockSettingsStorageTests extends AndroidTestCase { when(mockUserManager.getProfileParent(eq(3))).thenReturn(new UserInfo(0, "name", 0)); MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager, - mock(NotificationManager.class)); + mock(NotificationManager.class), mock(DevicePolicyManager.class)); mStorage = new LockSettingsStorageTestable(context, new File(getContext().getFilesDir(), "locksettings")); mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() { diff --git a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java index b63936fdffdf..8bceed45ab5f 100644 --- a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java +++ b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java @@ -17,6 +17,7 @@ package com.android.server; import android.app.NotificationManager; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.ContextWrapper; import android.os.UserManager; @@ -25,12 +26,14 @@ public class MockLockSettingsContext extends ContextWrapper { private UserManager mUserManager; private NotificationManager mNotificationManager; + private DevicePolicyManager mDevicePolicyManager; public MockLockSettingsContext(Context base, UserManager userManager, - NotificationManager notificationManager) { + NotificationManager notificationManager, DevicePolicyManager devicePolicyManager) { super(base); mUserManager = userManager; mNotificationManager = notificationManager; + mDevicePolicyManager = devicePolicyManager; } @Override @@ -39,6 +42,8 @@ public class MockLockSettingsContext extends ContextWrapper { return mUserManager; } else if (NOTIFICATION_SERVICE.equals(name)) { return mNotificationManager; + } else if (DEVICE_POLICY_SERVICE.equals(name)) { + return mDevicePolicyManager; } else { throw new RuntimeException("System service not mocked: " + name); } diff --git a/tests/net/Android.mk b/tests/net/Android.mk index 79f6e4d2f000..504d54eeb3a9 100644 --- a/tests/net/Android.mk +++ b/tests/net/Android.mk @@ -24,6 +24,7 @@ LOCAL_JAVA_LIBRARIES := \ android.test.runner LOCAL_PACKAGE_NAME := FrameworksNetTests +LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_CERTIFICATE := platform diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java index 3691cacdcae4..785e1ce20ab5 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java @@ -85,7 +85,7 @@ public class IpConnectivityMetricsTest extends TestCase { new Thread() { public void run() { for (int j = 0; j < nEvents; j++) { - assertTrue(logger.log(i * 100 + j, FAKE_EV)); + assertTrue(logger.log(1 + i * 100 + j, FAKE_EV)); } } }.start(); @@ -96,7 +96,7 @@ public class IpConnectivityMetricsTest extends TestCase { Iterator<ConnectivityMetricsEvent> iter = got.iterator(); for (int i = 0; i < nCallers; i++) { for (int j = 0; j < nEvents; j++) { - int expectedTimestamp = i * 100 + j; + int expectedTimestamp = 1 + i * 100 + j; assertEventsEqual(expectedEvent(expectedTimestamp), iter.next()); } } diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index 9e0f32137e89..0ab440641d53 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -23,6 +23,7 @@ import android.net.metrics.ConnectStats; import android.net.metrics.DnsEvent; import android.net.metrics.INetdEventListener; import android.net.metrics.IpConnectivityLog; +import android.os.Parcelable; import android.os.RemoteException; import android.system.OsConstants; import android.test.suitebuilder.annotation.SmallTest; @@ -165,8 +166,8 @@ public class NetdEventListenerServiceTest extends TestCase { // call onLost() asynchronously to logDnsAsync's onDnsEvent() calls. mCallbackCaptor.getValue().onLost(new Network(105)); - // do not verify unpredictable batch - verify(mLog, timeout(500).times(1)).log(any()); + // do not verify batch with unpredictable length + verify(mLog, timeout(500).times(1)).log(any(Parcelable.class)); } @SmallTest @@ -279,11 +280,7 @@ public class NetdEventListenerServiceTest extends TestCase { } void logDnsAsync(int netId, int[] latencies) { - new Thread() { - public void run() { - log(netId, latencies); - } - }.start(); + new Thread(() -> log(netId, latencies)).start(); } void verifyLoggedDnsEvents(DnsEvent... expected) { diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index ff5a5e9541df..aaff5d594920 100644 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java @@ -16,7 +16,6 @@ package android.graphics; -import android.text.FontConfig; import com.android.ide.common.rendering.api.AssetRepository; import com.android.ide.common.rendering.api.LayoutLog; import com.android.layoutlib.bridge.Bridge; @@ -293,12 +292,16 @@ public class FontFamily_Delegate { @LayoutlibDelegate /*package*/ static boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font, - int ttcIndex, List<FontConfig.Axis> listOfAxis, - int weight, boolean isItalic) { + int ttcIndex, int weight, boolean isItalic) { assert false : "The only client of this method has been overriden."; return false; } + @LayoutlibDelegate + /*package*/ static void nAddAxisValue(long builderPtr, int tag, float value) { + assert false : "The only client of this method has been overriden."; + } + static boolean addFont(long builderPtr, final String path, final int weight, final boolean isItalic) { final FontFamily_Delegate delegate = getDelegate(builderPtr); diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index aa1f00dee42e..1bb56e3be415 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -964,8 +964,9 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, char[] text, - int contextStart, int contextLength, int flags, int offset, int cursorOpt) { + /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr, + char[] text, int contextStart, int contextLength, int flags, int offset, + int cursorOpt) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "Paint.getTextRunCursor is not supported.", null, null /*data*/); @@ -973,8 +974,8 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, String text, - int contextStart, int contextEnd, int flags, int offset, int cursorOpt) { + /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr, + String text, int contextStart, int contextEnd, int flags, int offset, int cursorOpt) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "Paint.getTextRunCursor is not supported.", null, null /*data*/); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java index 7582fda6a0fb..4dfe47be0ef6 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java @@ -96,18 +96,6 @@ public final class BridgeWindowSession implements IWindowSession { } @Override - public void repositionChild(IWindow window, int left, int top, int right, int bottom, - long deferTransactionUntilFrame, Rect outFrame) { - // pass for now. - return; - } - - @Override - public void performDeferredDestroy(IWindow window) { - // pass for now. - } - - @Override public boolean outOfMemory(IWindow window) throws RemoteException { return false; } diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk index eac49d20b88d..8dc244f086cc 100644 --- a/wifi/tests/Android.mk +++ b/wifi/tests/Android.mk @@ -58,5 +58,6 @@ LOCAL_JAVA_LIBRARIES := \ android.test.runner \ LOCAL_PACKAGE_NAME := FrameworksWifiApiTests +LOCAL_COMPATIBILITY_SUITE := device-tests include $(BUILD_PACKAGE) |