diff options
53 files changed, 950 insertions, 418 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 0fca78d5e8dc..6fc1820c3c36 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1866,6 +1866,10 @@ public class Notification implements Parcelable } else { parcel.writeInt(0); } + if (mLargeIcon == null && largeIcon != null) { + // you snuck an icon in here without using the builder; let's try to keep it + mLargeIcon = Icon.createWithBitmap(largeIcon); + } if (mLargeIcon != null) { parcel.writeInt(1); mLargeIcon.writeToParcel(parcel, 0); @@ -1986,6 +1990,10 @@ public class Notification implements Parcelable new Throwable()); } + if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { + extras.putBoolean(EXTRA_SHOW_WHEN, true); + } + // ensure that any information already set directly is preserved final Notification.Builder builder = new Notification.Builder(context, this); @@ -2269,6 +2277,14 @@ public class Notification implements Parcelable Collections.addAll(mPersonList, mN.extras.getStringArray(EXTRA_PEOPLE)); } + if (mN.getSmallIcon() == null && mN.icon != 0) { + setSmallIcon(mN.icon); + } + + if (mN.getLargeIcon() == null && mN.largeIcon != null) { + setLargeIcon(mN.largeIcon); + } + String templateClass = mN.extras.getString(EXTRA_TEMPLATE); if (!TextUtils.isEmpty(templateClass)) { final Class<? extends Style> styleClass @@ -3171,8 +3187,8 @@ public class Notification implements Parcelable } private void resetContentMargins(RemoteViews contentView) { - contentView.setViewLayoutMarginEnd(R.id.line1, 0); - contentView.setViewLayoutMarginEnd(R.id.text, 0); + contentView.setViewLayoutMarginEndDimen(R.id.line1, 0); + contentView.setViewLayoutMarginEndDimen(R.id.text, 0); } private RemoteViews applyStandardTemplate(int resId) { @@ -3218,7 +3234,7 @@ public class Notification implements Parcelable contentView.setViewVisibility(textId, View.VISIBLE); } - setContentMinHeight(contentView, showProgress || mN.mLargeIcon != null); + setContentMinHeight(contentView, showProgress || mN.hasLargeIcon()); return contentView; } @@ -3262,15 +3278,17 @@ public class Notification implements Parcelable } private void bindLargeIcon(RemoteViews contentView) { + if (mN.mLargeIcon == null && mN.largeIcon != null) { + mN.mLargeIcon = Icon.createWithBitmap(mN.largeIcon); + } if (mN.mLargeIcon != null) { contentView.setViewVisibility(R.id.right_icon, View.VISIBLE); contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon); processLargeLegacyIcon(mN.mLargeIcon, contentView); - int endMargin = mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_picture_margin); - contentView.setViewLayoutMarginEnd(R.id.line1, endMargin); - contentView.setViewLayoutMarginEnd(R.id.text, endMargin); - contentView.setViewLayoutMarginEnd(R.id.progress, endMargin); + int endMargin = R.dimen.notification_content_picture_margin; + contentView.setViewLayoutMarginEndDimen(R.id.line1, endMargin); + contentView.setViewLayoutMarginEndDimen(R.id.text, endMargin); + contentView.setViewLayoutMarginEndDimen(R.id.progress, endMargin); } } @@ -3369,6 +3387,9 @@ public class Notification implements Parcelable } private void bindSmallIcon(RemoteViews contentView) { + if (mN.mSmallIcon == null && mN.icon != 0) { + mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon); + } contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon); processSmallIconColor(mN.mSmallIcon, contentView); } @@ -3394,6 +3415,8 @@ public class Notification implements Parcelable big.setTextViewText(R.id.notification_material_reply_text_2, null); big.setViewVisibility(R.id.notification_material_reply_text_3, View.GONE); big.setTextViewText(R.id.notification_material_reply_text_3, null); + + big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, 0); } private RemoteViews applyStandardTemplateWithActions(int layoutId) { @@ -3416,6 +3439,8 @@ public class Notification implements Parcelable if (N > 0) { big.setViewVisibility(R.id.actions_container, View.VISIBLE); big.setViewVisibility(R.id.actions, View.VISIBLE); + big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, + R.dimen.notification_action_list_height); if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS; for (int i=0; i<N; i++) { Action action = mActions.get(i); @@ -3564,6 +3589,8 @@ public class Notification implements Parcelable mStyle = null; Icon largeIcon = mN.mLargeIcon; mN.mLargeIcon = null; + Bitmap largeIconLegacy = mN.largeIcon; + mN.largeIcon = null; Bundle publicExtras = new Bundle(); publicExtras.putBoolean(EXTRA_SHOW_WHEN, savedBundle.getBoolean(EXTRA_SHOW_WHEN)); @@ -3577,6 +3604,7 @@ public class Notification implements Parcelable final RemoteViews publicView = applyStandardTemplate(getBaseLayoutResource()); mN.extras = savedBundle; mN.mLargeIcon = largeIcon; + mN.largeIcon = largeIconLegacy; mStyle = style; return publicView; } @@ -3873,6 +3901,10 @@ public class Notification implements Parcelable } } + private boolean hasLargeIcon() { + return mLargeIcon != null || largeIcon != null; + } + /** * @return true if the notification will show the time; false otherwise * @hide @@ -4179,7 +4211,7 @@ public class Notification implements Parcelable contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(mSummaryText)); contentView.setViewVisibility(R.id.text, View.VISIBLE); } - mBuilder.setContentMinHeight(contentView, mBuilder.mN.mLargeIcon != null); + mBuilder.setContentMinHeight(contentView, mBuilder.mN.hasLargeIcon()); if (mBigLargeIconSet) { mBuilder.mN.mLargeIcon = oldLargeIcon; @@ -4334,7 +4366,7 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.big_text, TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE); contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines(builder)); - contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.mLargeIcon != null); + contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.hasLargeIcon()); } private static int calculateMaxLines(Builder builder) { @@ -4604,11 +4636,10 @@ public class Notification implements Parcelable } int i=0; - int titlePadding = mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_messaging_spacing); - contentView.setViewLayoutMarginBottom(R.id.line1, hasTitle ? titlePadding : 0); + contentView.setViewLayoutMarginBottomDimen(R.id.line1, + hasTitle ? R.dimen.notification_messaging_spacing : 0); contentView.setInt(R.id.notification_messaging, "setNumIndentLines", - mBuilder.mN.mLargeIcon == null ? 0 : (hasTitle ? 1 : 2)); + !mBuilder.mN.hasLargeIcon() ? 0 : (hasTitle ? 1 : 2)); int contractedChildId = View.NO_ID; Message contractedMessage = findLatestIncomingMessage(); @@ -4981,12 +5012,11 @@ public class Notification implements Parcelable final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0); final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE); boolean hasProgress = max != 0 || ind; - if (mBuilder.mN.mLargeIcon != null && !hasProgress) { - endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_picture_margin); + if (mBuilder.mN.hasLargeIcon() && !hasProgress) { + endMargin = R.dimen.notification_content_picture_margin; } } - contentView.setViewLayoutMarginEnd(id, endMargin); + contentView.setViewLayoutMarginEndDimen(id, endMargin); } } @@ -5171,13 +5201,11 @@ public class Notification implements Parcelable } handleImage(view); // handle the content margin - int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_margin_end);; - if (mBuilder.mN.mLargeIcon != null) { - endMargin += mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_picture_margin); + int endMargin = R.dimen.notification_content_margin_end; + if (mBuilder.mN.hasLargeIcon()) { + endMargin = R.dimen.notification_content_plus_picture_margin_end; } - view.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin); + view.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin); return view; } @@ -5187,7 +5215,7 @@ public class Notification implements Parcelable int actionsInCompact = mActionsToShowInCompact == null ? 0 : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT); - if (mBuilder.mN.mLargeIcon == null && actionCount <= actionsInCompact) { + if (!mBuilder.mN.hasLargeIcon() && actionCount <= actionsInCompact) { return null; } RemoteViews big = mBuilder.applyStandardTemplate( @@ -5207,9 +5235,9 @@ public class Notification implements Parcelable } private void handleImage(RemoteViews contentView) { - if (mBuilder.mN.mLargeIcon != null) { - contentView.setViewLayoutMarginEnd(R.id.line1, 0); - contentView.setViewLayoutMarginEnd(R.id.text, 0); + if (mBuilder.mN.hasLargeIcon()) { + contentView.setViewLayoutMarginEndDimen(R.id.line1, 0); + contentView.setViewLayoutMarginEndDimen(R.id.text, 0); } } @@ -5324,13 +5352,11 @@ public class Notification implements Parcelable remoteViews.addView(R.id.notification_main_column, customContent); } // also update the end margin if there is an image - int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_margin_end); - if (mBuilder.mN.mLargeIcon != null) { - endMargin += mBuilder.mContext.getResources().getDimensionPixelSize( - R.dimen.notification_content_picture_margin); + int endMargin = R.dimen.notification_content_margin_end; + if (mBuilder.mN.hasLargeIcon()) { + endMargin = R.dimen.notification_content_plus_picture_margin_end; } - remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin); + remoteViews.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin); } } diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index e98bb7e7a9fd..9a0cd564e35f 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -47,6 +47,8 @@ public abstract class DevicePolicyManagerInternal { * Gets the packages whose widget providers are white-listed to be * available in the parent user. * + * <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held. + * * @param profileId The profile id. * @return The list of packages if such or empty list if there are * no white-listed packages or the profile id is not a managed @@ -58,6 +60,8 @@ public abstract class DevicePolicyManagerInternal { * Adds a listener for changes in the white-listed packages to show * cross-profile app widgets. * + * <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held. + * * @param listener The listener to add. */ public abstract void addOnCrossProfileWidgetProvidersChangeListener( @@ -66,6 +70,9 @@ public abstract class DevicePolicyManagerInternal { /** * Checks if an app with given uid is an active device admin of its user and has the policy * specified. + * + * <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held. + * * @param uid App uid. * @param reqPolicy Required policy, for policies see {@link DevicePolicyManager}. * @return true if the uid is an active admin with the given policy. @@ -77,6 +84,8 @@ public abstract class DevicePolicyManagerInternal { * suspended by the admin. This assumes that {@param packageName} is suspended by the * device/profile owner. The caller should check if the package is suspended or not. * + * <p>This method does not take the DPMS lock. Safe to be called from anywhere. + * * @param packageName The package that is suspended * @param userId The user having the suspended package. * @return The intent to trigger the admin support dialog. diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 6dc5ff7c427a..1f745185d01b 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -17,6 +17,7 @@ package android.widget; import android.annotation.ColorInt; +import android.annotation.DimenRes; import android.app.ActivityManager.StackId; import android.app.ActivityOptions; import android.app.ActivityThread; @@ -1850,13 +1851,13 @@ public class RemoteViews implements Parcelable, Filter { /** * Helper action to set layout params on a View. */ - private class LayoutParamAction extends Action { + private static class LayoutParamAction extends Action { /** Set marginEnd */ - public static final int LAYOUT_MARGIN_END = 1; + public static final int LAYOUT_MARGIN_END_DIMEN = 1; /** Set width */ public static final int LAYOUT_WIDTH = 2; - public static final int LAYOUT_MARGIN_BOTTOM = 3; + public static final int LAYOUT_MARGIN_BOTTOM_DIMEN = 3; /** * @param viewId ID of the view alter @@ -1893,15 +1894,17 @@ public class RemoteViews implements Parcelable, Filter { return; } switch (property) { - case LAYOUT_MARGIN_END: + case LAYOUT_MARGIN_END_DIMEN: if (layoutParams instanceof ViewGroup.MarginLayoutParams) { - ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(value); + int resolved = resolveDimenPixelOffset(target, value); + ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(resolved); target.setLayoutParams(layoutParams); } break; - case LAYOUT_MARGIN_BOTTOM: + case LAYOUT_MARGIN_BOTTOM_DIMEN: if (layoutParams instanceof ViewGroup.MarginLayoutParams) { - ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = value; + int resolved = resolveDimenPixelOffset(target, value); + ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = resolved; target.setLayoutParams(layoutParams); } break; @@ -1914,6 +1917,13 @@ public class RemoteViews implements Parcelable, Filter { } } + private static int resolveDimenPixelOffset(View target, int value) { + if (value == 0) { + return 0; + } + return target.getContext().getResources().getDimensionPixelOffset(value); + } + public String getActionName() { return "LayoutParamAction" + property + "."; } @@ -2870,27 +2880,36 @@ public class RemoteViews implements Parcelable, Filter { * Hidden for now since we don't want to support this for all different layout margins yet. * * @param viewId The id of the view to change - * @param endMargin the left padding in pixels + * @param endMarginDimen a dimen resource to read the margin from or 0 to clear the margin. */ - public void setViewLayoutMarginEnd(int viewId, int endMargin) { - addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_END, endMargin)); + public void setViewLayoutMarginEndDimen(int viewId, @DimenRes int endMarginDimen) { + addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_END_DIMEN, + endMarginDimen)); } /** * Equivalent to setting {@link android.view.ViewGroup.MarginLayoutParams#bottomMargin}. * + * @param bottomMarginDimen a dimen resource to read the margin from or 0 to clear the margin. * @hide */ - public void setViewLayoutMarginBottom(int viewId, int bottomMargin) { - addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_BOTTOM, - bottomMargin)); + public void setViewLayoutMarginBottomDimen(int viewId, @DimenRes int bottomMarginDimen) { + addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_BOTTOM_DIMEN, + bottomMarginDimen)); } /** * Equivalent to setting {@link android.view.ViewGroup.LayoutParams#width}. + * + * @param layoutWidth one of 0, MATCH_PARENT or WRAP_CONTENT. Other sizes are not allowed + * because they behave poorly when the density changes. * @hide */ public void setViewLayoutWidth(int viewId, int layoutWidth) { + if (layoutWidth != 0 && layoutWidth != ViewGroup.LayoutParams.MATCH_PARENT + && layoutWidth != ViewGroup.LayoutParams.WRAP_CONTENT) { + throw new IllegalArgumentException("Only supports 0, WRAP_CONTENT and MATCH_PARENT"); + } mActions.add(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_WIDTH, layoutWidth)); } diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java index a028449e39d7..716997f815dc 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java +++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java @@ -41,6 +41,7 @@ import android.view.inputmethod.InputMethodSubtype; import android.view.textservice.SpellCheckerInfo; import android.view.textservice.TextServicesManager; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; @@ -83,6 +84,17 @@ public class InputMethodUtils { Locale.UK, // "en_GB" }; + // A temporary workaround for the performance concerns in + // #getImplicitlyApplicableSubtypesLocked(Resources, InputMethodInfo). + // TODO: Optimize all the critical paths including this one. + private static final Object sCacheLock = new Object(); + @GuardedBy("sCacheLock") + private static LocaleList sCachedSystemLocales; + @GuardedBy("sCacheLock") + private static InputMethodInfo sCachedInputMethodInfo; + @GuardedBy("sCacheLock") + private static ArrayList<InputMethodSubtype> sCachedResult; + private InputMethodUtils() { // This utility class is not publicly instantiable. } @@ -498,6 +510,32 @@ public class InputMethodUtils { @VisibleForTesting public static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked( Resources res, InputMethodInfo imi) { + final LocaleList systemLocales = res.getConfiguration().getLocales(); + + synchronized (sCacheLock) { + // We intentionally do not use InputMethodInfo#equals(InputMethodInfo) here because + // it does not check if subtypes are also identical. + if (systemLocales.equals(sCachedSystemLocales) && sCachedInputMethodInfo == imi) { + return new ArrayList<>(sCachedResult); + } + } + + // Note: Only resource info in "res" is used in getImplicitlyApplicableSubtypesLockedImpl(). + // TODO: Refactor getImplicitlyApplicableSubtypesLockedImpl() so that it can receive + // LocaleList rather than Resource. + final ArrayList<InputMethodSubtype> result = + getImplicitlyApplicableSubtypesLockedImpl(res, imi); + synchronized (sCacheLock) { + // Both LocaleList and InputMethodInfo are immutable. No need to copy them here. + sCachedSystemLocales = systemLocales; + sCachedInputMethodInfo = imi; + sCachedResult = new ArrayList<>(result); + } + return result; + } + + private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLockedImpl( + Resources res, InputMethodInfo imi) { final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi); final LocaleList systemLocales = res.getConfiguration().getLocales(); final String systemLocale = systemLocales.get(0).toString(); diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml index 4670dcabe211..caeb43ac5bbe 100644 --- a/core/res/res/layout/notification_material_action_list.xml +++ b/core/res/res/layout/notification_material_action_list.xml @@ -17,7 +17,8 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/actions_container" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:layout_gravity="bottom"> <com.android.internal.widget.NotificationActionListLayout android:id="@+id/actions" android:layout_width="match_parent" diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml index c54fa1895dfa..8b0b4763d7fa 100644 --- a/core/res/res/layout/notification_template_material_big_base.xml +++ b/core/res/res/layout/notification_template_material_big_base.xml @@ -14,7 +14,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> -<LinearLayout +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/status_bar_latest_event_content" android:layout_width="match_parent" @@ -22,43 +22,49 @@ android:orientation="vertical" android:tag="big" > - <FrameLayout - android:id="@+id/status_bar_latest_event_content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="top" - android:tag="base" - > - <include layout="@layout/notification_template_header" /> - <LinearLayout - android:id="@+id/notification_main_column" + <LinearLayout + android:id="@+id/notification_action_list_margin_target" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="top" - android:layout_marginStart="@dimen/notification_content_margin_start" - android:layout_marginEnd="@dimen/notification_content_margin_end" - android:layout_marginTop="@dimen/notification_content_margin_top" - android:layout_marginBottom="@dimen/notification_content_margin_bottom" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/notification_action_list_height" android:orientation="vertical" > - <include layout="@layout/notification_template_part_line1" /> - <include layout="@layout/notification_template_text" /> - </LinearLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:layout_marginStart="@dimen/notification_content_margin_start" - android:layout_marginBottom="15dp" - android:layout_marginEnd="@dimen/notification_content_margin_end"> - <include layout="@layout/notification_template_progress" /> + android:layout_gravity="top" + > + <include layout="@layout/notification_template_header" /> + <LinearLayout + android:id="@+id/notification_main_column" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="top" + android:layout_marginStart="@dimen/notification_content_margin_start" + android:layout_marginEnd="@dimen/notification_content_margin_end" + android:layout_marginTop="@dimen/notification_content_margin_top" + android:layout_marginBottom="@dimen/notification_content_margin_bottom" + android:orientation="vertical" + > + <include layout="@layout/notification_template_part_line1" /> + <include layout="@layout/notification_template_text" /> + </LinearLayout> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:layout_marginStart="@dimen/notification_content_margin_start" + android:layout_marginBottom="15dp" + android:layout_marginEnd="@dimen/notification_content_margin_end"> + <include layout="@layout/notification_template_progress" /> + </FrameLayout> + <include layout="@layout/notification_template_right_icon" /> </FrameLayout> - <include layout="@layout/notification_template_right_icon" /> - </FrameLayout> - <ViewStub android:layout="@layout/notification_material_reply_text" - android:id="@+id/notification_material_reply_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - /> + <ViewStub android:layout="@layout/notification_material_reply_text" + android:id="@+id/notification_material_reply_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> + </LinearLayout> <include layout="@layout/notification_material_action_list" /> -</LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml index d87b9d90e48f..83c0fec004b6 100644 --- a/core/res/res/layout/notification_template_material_big_picture.xml +++ b/core/res/res/layout/notification_template_material_big_picture.xml @@ -30,6 +30,7 @@ android:layout_marginTop="@dimen/notification_content_margin_top" android:clipToPadding="false" android:orientation="vertical" + android:id="@+id/notification_action_list_margin_target" > <LinearLayout android:id="@+id/notification_main_column" @@ -60,6 +61,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> - <include layout="@layout/notification_material_action_list" /> </LinearLayout> + <include layout="@layout/notification_material_action_list" /> </FrameLayout> diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml index 71600ef7b134..f4f783ecc6fb 100644 --- a/core/res/res/layout/notification_template_material_big_text.xml +++ b/core/res/res/layout/notification_template_material_big_text.xml @@ -24,10 +24,12 @@ <include layout="@layout/notification_template_header" /> <LinearLayout + android:id="@+id/notification_action_list_margin_target" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="top" android:layout_marginTop="@dimen/notification_content_margin_top" + android:layout_marginBottom="@dimen/notification_action_list_height" android:clipToPadding="false" android:orientation="vertical"> @@ -61,7 +63,7 @@ android:id="@+id/notification_material_reply_container" android:layout_width="match_parent" android:layout_height="wrap_content" /> - <include layout="@layout/notification_material_action_list" /> </LinearLayout> + <include layout="@layout/notification_material_action_list" /> <include layout="@layout/notification_template_right_icon" /> </FrameLayout> diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml index 0e93d0bc1635..7820e39e777c 100644 --- a/core/res/res/layout/notification_template_material_inbox.xml +++ b/core/res/res/layout/notification_template_material_inbox.xml @@ -23,6 +23,7 @@ > <include layout="@layout/notification_template_header" /> <LinearLayout + android:id="@+id/notification_action_list_margin_target" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="top" @@ -117,7 +118,7 @@ android:id="@+id/notification_material_reply_container" android:layout_width="match_parent" android:layout_height="wrap_content" /> - <include layout="@layout/notification_material_action_list" /> </LinearLayout> + <include layout="@layout/notification_material_action_list" /> <include layout="@layout/notification_template_right_icon" /> </FrameLayout> diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml index d95ff056c22a..07b1100ee93b 100644 --- a/core/res/res/layout/notification_template_material_messaging.xml +++ b/core/res/res/layout/notification_template_material_messaging.xml @@ -22,6 +22,7 @@ > <include layout="@layout/notification_template_header" /> <LinearLayout + android:id="@+id/notification_action_list_margin_target" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="top" @@ -74,7 +75,7 @@ /> </com.android.internal.widget.MessagingLinearLayout> </LinearLayout> - <include layout="@layout/notification_material_action_list" /> </LinearLayout> + <include layout="@layout/notification_material_action_list" /> <include layout="@layout/notification_template_right_icon" /> </FrameLayout> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 37fb8166e989..91d7227c6a60 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -148,12 +148,20 @@ <!-- The margin on the start of the content view --> <dimen name="notification_content_margin_start">16dp</dimen> - <!-- The margin on the end of the content view --> + <!-- The margin on the end of the content view + Keep in sync with notification_content_plus_picture_margin! --> <dimen name="notification_content_margin_end">16dp</dimen> - <!-- The margin on the end of the content view with a picture.--> + <!-- The margin on the end of the content view with a picture. + Keep in sync with notification_content_plus_picture_margin! --> <dimen name="notification_content_picture_margin">56dp</dimen> + <!-- The margin on the end of the content view with a picture, plus the standard + content end margin. + Keep equal to (notification_content_picture_margin + notification_content_margin_end)! + --> + <dimen name="notification_content_plus_picture_margin_end">72dp</dimen> + <!-- The height of the notification action list --> <dimen name="notification_action_list_height">56dp</dimen> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index abef7f8e91ac..7e9b57c7a49b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2602,6 +2602,9 @@ <java-symbol type="bool" name="config_supportPreRebootSecurityLogs" /> + <java-symbol type="dimen" name="notification_content_plus_picture_margin_end" /> + <java-symbol type="id" name="notification_action_list_margin_target" /> + <!-- Pinner Service --> <java-symbol type="array" name="config_defaultPinnerServiceFiles" /> diff --git a/docs/html-intl/intl/es/training/material/compatibility.jd b/docs/html-intl/intl/es/training/material/compatibility.jd index ad2e953fed4f..d2cb9aacb622 100644 --- a/docs/html-intl/intl/es/training/material/compatibility.jd +++ b/docs/html-intl/intl/es/training/material/compatibility.jd @@ -123,7 +123,7 @@ con esquinas redondeadas.</li> <h3>Dependencias</h3> <p>Para usar estas caracterÃsticas en versiones de Android anteriores a la 5.0 (API nivel 21), incluye -en tu proyecto la Biblioteca de soporte v7 de Android como una <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependencia de Gradle</a>:</p> +en tu proyecto la Biblioteca de soporte v7 de Android como una <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependencia de Gradle</a>:</p> <pre> dependencies { diff --git a/docs/html-intl/intl/in/training/material/compatibility.jd b/docs/html-intl/intl/in/training/material/compatibility.jd index d57c7bef1810..ef444c359b57 100644 --- a/docs/html-intl/intl/in/training/material/compatibility.jd +++ b/docs/html-intl/intl/in/training/material/compatibility.jd @@ -123,7 +123,7 @@ Android v7 Support Library dengan pembatasan ini:</p> <h3>Dependensi</h3> <p>Untuk menggunakan fitur-fitur ini di versi Android sebelum 5.0 (API level 21), sertakan -Android v7 Support Library dalam proyek Anda sebagai <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependensi Gradle</a>:</p> +Android v7 Support Library dalam proyek Anda sebagai <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a>:</p> <pre> dependencies { diff --git a/docs/html-intl/intl/ja/training/material/compatibility.jd b/docs/html-intl/intl/ja/training/material/compatibility.jd index 0f8922fec4a3..25811704aac2 100644 --- a/docs/html-intl/intl/ja/training/material/compatibility.jd +++ b/docs/html-intl/intl/ja/training/material/compatibility.jd @@ -122,7 +122,7 @@ android.support.v7.widget.CardView} ウィジェット㯠Android v7 サãƒãƒ¼ãƒ <h3>ä¾å˜é–¢ä¿‚</h3> -<p>5.0(API レベル 21)よりå‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Android ã§ã“ã‚Œã‚‰ã®æ©Ÿèƒ½ã‚’使用ã™ã‚‹ã«ã¯ã€Android v7 サãƒãƒ¼ãƒˆ ライブラリを <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle ä¾å˜é–¢ä¿‚</a>ã¨ã—ã¦ãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã«å«ã‚ã¾ã™ã€‚ +<p>5.0(API レベル 21)よりå‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Android ã§ã“ã‚Œã‚‰ã®æ©Ÿèƒ½ã‚’使用ã™ã‚‹ã«ã¯ã€Android v7 サãƒãƒ¼ãƒˆ ライブラリを <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle ä¾å˜é–¢ä¿‚</a>ã¨ã—ã¦ãƒ—ãƒã‚¸ã‚§ã‚¯ãƒˆã«å«ã‚ã¾ã™ã€‚ </p> <pre> diff --git a/docs/html-intl/intl/ko/training/material/compatibility.jd b/docs/html-intl/intl/ko/training/material/compatibility.jd index 266cd7c62f9b..5bb84340c4f5 100644 --- a/docs/html-intl/intl/ko/training/material/compatibility.jd +++ b/docs/html-intl/intl/ko/training/material/compatibility.jd @@ -122,7 +122,7 @@ android.support.v7.widget.CardView} ìœ„ì ¯ì€ Android v7 ì§€ì› ë¼ì´ë¸ŒëŸ¬ë¦¬ë <h3>ì¢…ì† ì‚¬í•</h3> -<p>Android 5.0(API ë ˆë²¨ 21) ì´ì „ ë²„ì „ì—서 ì´ëŸ¬í•œ ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ë ¤ë©´ 프로ì íŠ¸ì— Android v7 ì§€ì› ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle ì¢…ì† ì‚¬í•</a>으로 í¬í•¨í•©ë‹ˆë‹¤. +<p>Android 5.0(API ë ˆë²¨ 21) ì´ì „ ë²„ì „ì—서 ì´ëŸ¬í•œ ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ë ¤ë©´ 프로ì íŠ¸ì— Android v7 ì§€ì› ë¼ì´ë¸ŒëŸ¬ë¦¬ë¥¼ <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle ì¢…ì† ì‚¬í•</a>으로 í¬í•¨í•©ë‹ˆë‹¤. </p> <pre> diff --git a/docs/html-intl/intl/pt-br/training/material/compatibility.jd b/docs/html-intl/intl/pt-br/training/material/compatibility.jd index 2540df118aeb..d242c0cf1641 100644 --- a/docs/html-intl/intl/pt-br/training/material/compatibility.jd +++ b/docs/html-intl/intl/pt-br/training/material/compatibility.jd @@ -123,7 +123,7 @@ Biblioteca de Suporte v7 do Android com as seguintes limitações:</p> <h3>Dependências</h3> <p>Para usar esses recursos em versões anteriores ao Android 5.0 (API de nÃvel 21), inclua a -Biblioteca de Suporte v7 do Android no projeto como uma <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependência de Gradle</a>:</p> +Biblioteca de Suporte v7 do Android no projeto como uma <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependência de Gradle</a>:</p> <pre> dependencies { diff --git a/docs/html-intl/intl/ru/training/material/compatibility.jd b/docs/html-intl/intl/ru/training/material/compatibility.jd index b7ca338045fa..1f1d63053891 100644 --- a/docs/html-intl/intl/ru/training/material/compatibility.jd +++ b/docs/html-intl/intl/ru/training/material/compatibility.jd @@ -123,7 +123,7 @@ android.support.v7.widget.CardView} имеютÑÑ Ð² более ранних в <h3>ЗавиÑимоÑти</h3> <p>Чтобы воÑпользоватьÑÑ Ñтими возможноÑÑ‚Ñми в верÑиÑÑ… Android, предшеÑтвующих 5.0 (уровень API 21), включите в Ñвой проект вÑпомогательную библиотеку -Android v7 как <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">завиÑимоÑть Gradle</a>:</p> +Android v7 как <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">завиÑимоÑть Gradle</a>:</p> <pre> dependencies { diff --git a/docs/html-intl/intl/vi/training/material/compatibility.jd b/docs/html-intl/intl/vi/training/material/compatibility.jd index 65e813129704..e19a745dd9b9 100644 --- a/docs/html-intl/intl/vi/training/material/compatibility.jd +++ b/docs/html-intl/intl/vi/training/material/compatibility.jd @@ -123,7 +123,7 @@ Thư viện Há»— trợ v7 cá»§a Android vá»›i những hạn chế sau:</p> <h3>Phụ thuá»™c</h3> <p>Äể sá» dụng những tÃnh năng nà y trong các phiên bản Android trước 5.0 (API mức 21), hãy thêm -Thư viện Há»— trợ v7 cá»§a Android và o dá»± án cá»§a bạn như má»™t <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Phần phụ thuá»™c Gradle</a>:</p> +Thư viện Há»— trợ v7 cá»§a Android và o dá»± án cá»§a bạn như má»™t <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Phần phụ thuá»™c Gradle</a>:</p> <pre> dependencies { diff --git a/docs/html-intl/intl/zh-cn/training/material/compatibility.jd b/docs/html-intl/intl/zh-cn/training/material/compatibility.jd index aa23d4b5e614..9ba85691f22f 100644 --- a/docs/html-intl/intl/zh-cn/training/material/compatibility.jd +++ b/docs/html-intl/intl/zh-cn/training/material/compatibility.jd @@ -123,7 +123,7 @@ android.support.v7.widget.CardView} å°ç»„ä»¶å¯é€šè¿‡ Android v7 支æŒå†…å®¹åº <h3>ä¾èµ–项</h3> <p>如果è¦åœ¨ Android 5.0(API 级别 21)之å‰çš„ Android 版本ä¸ä½¿ç”¨è¿™äº›åŠŸèƒ½ï¼Œè¯·å°† -Android v7 支æŒå†…容库作为 <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle ä¾èµ–项</a>包括在您的项目ä¸ï¼š</p> +Android v7 支æŒå†…容库作为 <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle ä¾èµ–项</a>包括在您的项目ä¸ï¼š</p> <pre> dependencies { diff --git a/docs/html-intl/intl/zh-tw/training/material/compatibility.jd b/docs/html-intl/intl/zh-tw/training/material/compatibility.jd index 767788bf75be..7d3cddeb5413 100644 --- a/docs/html-intl/intl/zh-tw/training/material/compatibility.jd +++ b/docs/html-intl/intl/zh-tw/training/material/compatibility.jd @@ -122,7 +122,7 @@ android.support.v7.widget.CardView} å°å·¥å…·ï¼Œä½†æœ‰ä¸‹åˆ—é™åˆ¶ï¼š <h3>ç›¸ä¾æ€§</h3> -<p>如果è¦åœ¨ Android 5.0 (API 級別 21) 以å‰çš„版本ä¸ä½¿ç”¨é€™äº›åŠŸèƒ½ï¼Œè«‹åœ¨æ‚¨çš„å°ˆæ¡ˆä¸åŒ…å« Android v7 支æ´ç¨‹å¼åº«åšç‚º <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle ç›¸ä¾æ€§</a>: +<p>如果è¦åœ¨ Android 5.0 (API 級別 21) 以å‰çš„版本ä¸ä½¿ç”¨é€™äº›åŠŸèƒ½ï¼Œè«‹åœ¨æ‚¨çš„å°ˆæ¡ˆä¸åŒ…å« Android v7 支æ´ç¨‹å¼åº«åšç‚º <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle ç›¸ä¾æ€§</a>: </p> <pre> diff --git a/docs/html/guide/practices/verifying-apps-art.jd b/docs/html/guide/practices/verifying-apps-art.jd index 8a88222ee2a0..217c65c9fcd2 100644 --- a/docs/html/guide/practices/verifying-apps-art.jd +++ b/docs/html/guide/practices/verifying-apps-art.jd @@ -63,7 +63,7 @@ ART. This document discusses some of these issues.</p> java.lang.System#gc() System.gc()} to prompt garbage collection (GC). This should be far less necessary with ART, particularly if you're invoking garbage collection to prevent <a -href="{@docRoot}/tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type +href="{@docRoot}tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type occurrences or to reduce fragmentation. You can verify which runtime is in use by calling {@link java.lang.System#getProperty(java.lang.String) System.getProperty("java.vm.version")}. If ART is in use, the property's value diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd index 606b38fdd691..f2bc11136d58 100644 --- a/docs/html/preview/api-overview.jd +++ b/docs/html/preview/api-overview.jd @@ -37,6 +37,7 @@ page.image=images/cards/card-n-apis_2x.png <li><a href="#apk_signature_v2">APK Signature Scheme v2</a></li> <li><a href="#scoped_directory_access">Scoped Directory Access</a></li> <li><a href="#keyboard_shortcuts_helper">Keyboard Shortcuts Helper</a></li> + <li><a href="#custom_pointer_api">Custom Pointer API</a></li> <li><a href="#sustained_performance_api">Sustained Performance API</a></li> <li><a href="#vr">VR Support</a></li> <li><a href="#print_svc">Print Service Enhancements</a></li> @@ -843,18 +844,46 @@ Directory Access</a> developer documentation.</p> <h2 id="keyboard_shortcuts_helper">Keyboard Shortcuts Helper</h2> <p> -In Android N, the user can press "Alt + /" to trigger a <em>Keyboard Shortcuts</em> -screen that displays all shortcuts available both from the system and from -the app in focus. These are retrieved automatically from the app’s menu if -available, but developers can provide their own fine-tuned shortcuts lists -for the screen. You can do this by overriding the new -<code>Activity.onProvideKeyboardShortcuts()</code> method, described in the downloadable -<a href="{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>. + In Android N, the user can press <strong>Meta + /</strong> to trigger a + <em>Keyboard Shortcuts</em> screen that displays all shortcuts available both + from the system and from the app in focus. The system retrieves these + shortcuts automatically from the app’s menu if the shortcuts exist. You can + also provide your own fine-tuned shortcuts lists for the screen. You can do + this by overriding the new <code>Activity.onProvideKeyboardShortcuts()</code> + method, described in the downloadable <a href= + "{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>. +</p> + +<p class="note"> + <strong>Note:</strong> The <strong>Meta</strong> key is not present on all + keyboards: on a Macintosh keyboard, it is the <strong>Command</strong> key, + on the Windows keyboard, it is the <strong>Windows</strong> key, and on the + Pixel C and the Chrome OS keyboards, it is the <strong>Search</strong> key. +</p> + +<p> + To trigger Keyboard Shortcuts Helper from anywhere in your app, call + {@code Activity.requestKeyboardShortcutsHelper()} for the relevant activity. +</p> + +<h2 id="custom_pointer_api"> + Custom Pointer API +</h2> + +<p> + Android N introduces the Custom Pointer API, which lets you customize the + appearance, visibility, and behavior of the pointer. This capability is + especially useful when a user is using a mouse or touchpad to interact with + UI objects. The default pointer uses a standard icon. This API also includes + advanced functionality such as changing the pointer icon's appearance based + on specific mouse or touchpad movements. </p> <p> -To trigger the Keyboard Shortcuts Helper from anywhere in your app, -call {@code Activity.requestKeyboardShortcutsHelper()} for the relevant activity. + To set a pointer icon, override the <code>onResolvePointerIcon()</code> + method of the <code>View</code> class. This method uses a + <code>PointerIcon</code> object to draw the icon that corresponds to a + specific motion event. </p> <h2 id="sustained_performance_api">Sustained Performance API</h2> diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd index 66dce7a5d0be..ece6b43efa81 100644 --- a/docs/html/preview/behavior-changes.jd +++ b/docs/html/preview/behavior-changes.jd @@ -612,5 +612,15 @@ as the return status when they invoke {@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}. </li> + <li>The JCA provider called <em>Crypto</em> is deprecated, because its only + algorithm, SHA1PRNG, is cryptographically weak. Apps can no longer use + SHA1PRNG to (insecurely) derive keys, because this provider is no longer + available. For more information, see the blog + post <a href= + "http://android-developers.blogspot.com/2016/06/security-crypto-provider-deprecated-in.html" + class="external-link">Security "Crypto" provider deprecated in Android + N</a>. + </li> + </ul> diff --git a/docs/html/preview/download-ota.jd b/docs/html/preview/download-ota.jd index 2058501dd9a9..18f3e8d01f0a 100644 --- a/docs/html/preview/download-ota.jd +++ b/docs/html/preview/download-ota.jd @@ -203,72 +203,72 @@ This is the Android SDK Preview License Agreement (the “License Agreementâ€). <tr id="bullhead"> <td>Nexus 5X <br>"bullhead"</td> <td><a href="#top" onclick="onDownload(this)" - >bullhead-ota-npd35k-b8cfbd80.zip</a><br> - MD5: 15fe2eba9b01737374196bdf0a792fe9<br> - SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283 + >bullhead-ota-npd56n-dd5c12ee.zip</a><br> + MD5: af9a82e9a78925ca9c1c7f5f6fb851ec<br> + SHA-1: e4aabd5634b7ebdeffa877cd9e49244c0be326e4 </td> </tr> <tr id="shamu"> <td>Nexus 6 <br>"shamu"</td> <td><a href="#top" onclick="onDownload(this)" - >shamu-ota-npd35k-078e6fa5.zip</a><br> - MD5: e8b12f7721c53af9a450f7058928a5fc<br> - SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a + >shamu-ota-npd56n-2818fd62.zip</a><br> + MD5: d8df396b187a8667889260e5464bd676<br> + SHA-1: c03c8ef8be587a574565855d4faa526254794e03 </td> </tr> <tr id="angler"> <td>Nexus 6P <br>"angler"</td> <td><a href="#top" onclick="onDownload(this)" - >angler-ota-npd35k-88457699.zip</a><br> - MD5: 3fac09fef759dde26e57cb80b20b6477<br> - SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c + >angler-ota-npd56n-d2f2611c.zip</a><br> + MD5: c3c206892d414d4fc7da892ff840eada<br> + SHA-1: 2bdc79409ace5e163ef014ae51977d0a71b83df5 </td> </tr> <tr id="volantis"> <td>Nexus 9 <br>"volantis"</td> <td><a href="#top" onclick="onDownload(this)" - >volantis-ota-npd35k-51dbae76.zip</a><br> - MD5: 58312c4a5971818ef5c77a3f446003da<br> - SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921 + >volantis-ota-npd56n-42228a60.zip</a><br> + MD5: c80cf483d8b3c014fc7b27f80957a158<br> + SHA-1: f437829320f47ea3aa5f8b70ce2f0bb3d30b3f4f </td> </tr> <tr id="volantisg"> <td>Nexus 9G <br>"volantisg"</td> <td><a href="#top" onclick="onDownload(this)" - >volantisg-ota-npd35k-834f047f.zip</a><br> - MD5: 92b7d1fa252f7394e70f957c72d4aac8<br> - SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361 + >volantisg-ota-npd56n-9b4dbaac.zip</a><br> + MD5: 9e55ac1650e4f07a662bafa7f082e91c<br> + SHA-1: b9982be56c2817d122664869a1fbe9b13e9c72f7 </td> </tr> <tr id="fugu"> <td>Nexus Player <br>"fugu"</td> <td><a href="#top" onclick="onDownload(this)" - >fugu-ota-npd35k-6ac91298.zip</a><br> - MD5: 1461622ad53ea842b2722fa7b49b8172<br> - SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931 + >fugu-ota-npd56n-b305968a.zip</a><br> + MD5: dfc980acad6772d8473ccaa9cbbb681a<br> + SHA-1: d7bf8192649dea970afda165d181b4eea07abd7d </td> </tr> <tr id="ryu"> <td>Pixel C <br>"ryu"</td> <td><a href="#top" onclick="onDownload(this)" - >ryu-ota-npd35k-a0b2347f.zip</a><br> - MD5: c60117f3640cc6db12386fd632289c7d<br> - SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3 + >ryu-ota-npd56n-5bf2fd66.zip</a><br> + MD5: 1699e4bacfbef16a75ae6cf3f2e3d886<br> + SHA-1: e20f3a8e43fcdd6acef21da80894afc8f9474e33 </td> </tr> <tr id="seed"> <td>General Mobile 4G (Android One) <br>"seed"</td> <td><a href="#top" onclick="onDownload(this)" - >seed_l8150-ota-npd35k-09897a1d.zip</a><br> - MD5: a55cf94f7cce0393ec6c0b35041766b7<br> - SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a + >seed_l8150-ota-npd56n-a322696c.zip</a><br> + MD5: afc0e363ad2fd7418423e189a339a8e9<br> + SHA-1: fc4d818878df51894eac29932dd0e9f6511329c6 </td> </tr> diff --git a/docs/html/preview/download.jd b/docs/html/preview/download.jd index b5405c7c934d..ad82211d0e65 100644 --- a/docs/html/preview/download.jd +++ b/docs/html/preview/download.jd @@ -302,72 +302,72 @@ This is the Android SDK Preview License Agreement (the “License Agreementâ€). <tr id="bullhead"> <td>Nexus 5X <br>"bullhead"</td> <td><a href="#top" onclick="onDownload(this)" - >bullhead-npd35k-factory-5ba40535.tgz</a><br> - MD5: b6c5d79a21815ee21db41822dcf61e9f<br> - SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c + >bullhead-npd56n-factory-996cac57.tgz</a><br> + MD5: 5aadba91f60de00d58dc6198ef5cc3ba<br> + SHA-1: 996cac575d83bde573315290da8f52cecc4127d2 </td> </tr> <tr id="shamu"> <td>Nexus 6 <br>"shamu"</td> <td><a href="#top" onclick="onDownload(this)" - >shamu-npd35k-factory-a33bf20c.tgz</a><br> - MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br> - SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c + >shamu-npd56n-factory-7936bf75.tgz</a><br> + MD5: b7ed0db569f3bc2d6655fe8d8cea0e13<br> + SHA-1: 7936bf75e6bfb771bd14485211a319b246311b96 </td> </tr> <tr id="angler"> <td>Nexus 6P <br>"angler"</td> <td><a href="#top" onclick="onDownload(this)" - >angler-npd35k-factory-81c341d5.tgz</a><br> - MD5: e93de7949433339856124c3729c15ebb<br> - SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd + >angler-npd56n-factory-1ce5ccad.tgz</a><br> + MD5: f296eccaed4e2526d6435df8cf0e8df1<br> + SHA-1: 1ce5ccad8a3eae143e0ecd9c7afbb1be2f1d41cc </td> </tr> <tr id="volantis"> <td>Nexus 9 <br>"volantis"</td> <td><a href="#top" onclick="onDownload(this)" - >volantis-npd35k-factory-2b50e19d.tgz</a><br> - MD5: 565be87ebb2d5937e2abe1a42645864b<br> - SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1 + >volantis-npd56n-factory-8b9f997e.tgz</a><br> + MD5: 111c2fe5777dd6aae71fb8ef35dda9d3<br> + SHA-1: 8b9f997ea39fdaf505527536bd346948ae1bae30 </td> </tr> <tr id="volantisg"> <td>Nexus 9G <br>"volantisg"</td> <td><a href="#top" onclick="onDownload(this)" - >volantisg-npd35k-factory-2e89ebe6.tgz</a><br> - MD5: a8464e15c6683fe2afa378a63e205fda<br> - SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678 + >volantisg-npd56n-factory-ef05106a.tgz</a><br> + MD5: 3a6f4d47b385966347bd26b7a922cd6e<br> + SHA-1: ef05106a9e3becea5673ea67d6c0cc21a2ec09d4 </td> </tr> <tr id="fugu"> <td>Nexus Player <br>"fugu"</td> <td><a href="#top" onclick="onDownload(this)" - >fugu-npd35k-factory-1de74874.tgz</a><br> - MD5: c0dbb7db671f61b2785da5001cedefcb<br> - SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873 + >fugu-npd56n-factory-a51674a1.tgz</a><br> + MD5: b75dc745a64848ea24124db8fa9252ed<br> + SHA-1: a51674a1303b17fec0405d513f9c0fe9f225780f </td> </tr> <tr id="ryu"> <td>Pixel C <br>"ryu"</td> <td><a href="#top" onclick="onDownload(this)" - >ryu-npd35k-factory-b4eed85d.tgz</a><br> - MD5: bdcb6f770e753668b5fadff2a6678e0d<br> - SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2 + >ryu-npd56n-factory-e36c49b1.tgz</a><br> + MD5: 0a2d660b09e19614a5b3573487b88066<br> + SHA-1: e36c49b184843cdfe10278aebc04ce50b6d670b6 </td> </tr> <tr id="seed"> <td>General Mobile 4G (Android One) <br>"seed"</td> <td><a href="#top" onclick="onDownload(this)" - >seed_l8150-npd35k-factory-5ab1212b.tgz</a><br> - MD5: 7d34a9774fdd6e025d485ce6cfc23c4c<br> - SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5 + >seed_l8150-npd56n-factory-dd5d4fd2.tgz</a><br> + MD5: 3420581b969af777753141dacc7f73b9<br> + SHA-1: dd5d4fd203f9c5dad658434c0ff370c411b78835 </td> </tr> diff --git a/docs/html/preview/features/direct-boot.jd b/docs/html/preview/features/direct-boot.jd index 3d442d0966ca..8351f4b4b10f 100644 --- a/docs/html/preview/features/direct-boot.jd +++ b/docs/html/preview/features/direct-boot.jd @@ -108,18 +108,25 @@ Direct Boot mode, use credential encrypted storage.</p> <h2 id="notification">Getting Notified of User Unlock</h2> -<p>Once the user unlocks the device after restart, your app can switch to +<p>When the user unlocks the device after restart, your app can switch to accessing credential encrypted storage and use regular system services that depend on user credentials.</p> <p>To get notified when the user unlocks the device after a reboot, register a {@link android.content.BroadcastReceiver} from a running component -to listen for the <code>ACTION_USER_UNLOCKED</code> message. Or, you can -receive the existing {@link android.content.Intent#ACTION_BOOT_COMPLETED -ACTION_BOOT_COMPLETED} message, which now indicates the device has booted and -the user has unlocked the device.</p> +to listen for unlock notification messages. When the user unlocks the device +after boot: +</p> +<ul> +<li>If your app has foreground processes that need immediate notification, +listen for the {@code ACTION_USER_UNLOCKED} message.</li> +<li>If your app only uses background processes that can act on a delayed +notification, listen for the +{@link android.content.Intent#ACTION_BOOT_COMPLETED ACTION_BOOT_COMPLETED} +message.</li> +</ul> -<p>You can directly query if the user has unlocked the device by calling +<p>If the user has unlocked the device, you can find out by calling <code>UserManager.isUserUnlocked()</code>.</p> <h2 id="migrating">Migrating Existing Data</h2> diff --git a/docs/html/topic/libraries/support-library/revisions.jd b/docs/html/topic/libraries/support-library/revisions.jd index 75257609cb30..88b0ca1fec0e 100644 --- a/docs/html/topic/libraries/support-library/revisions.jd +++ b/docs/html/topic/libraries/support-library/revisions.jd @@ -6,6 +6,124 @@ page.metaDescription=This page provides details about the Support Library packag <p>This page provides details about the Support Library package releases.</p> <div class="toggle-content opened"> + <p id="rev24-0-0"> + <a href="#" onclick="return toggleContent(this)"><img src= + "{@docRoot}assets/images/styles/disclosure_up.png" class= + "toggle-content-img" alt="">Android Support Library, revision 24.0.0</a> + <em>(June 2016)</em> + </p> + + <div class="toggle-content-toggleme"> + <dl> + <dt> + Changes for <a href= + "{@docRoot}tools/support-library/features.html#v4">v4 Support + Library</a>: + </dt> + + <dd> + <ul> + <li>Added <code>Fragment.commitNow()</code> + for synchronous commit + </li> + + <li>Added <code>NotificationCompat.MessagingStyle</code> + for multi-party conversations + </li> + + <li>Added <code>NotificationManagerCompat.areNotificationsEnabled()</code> + and <code>getImportance()</code> + </li> + + <li>{@link android.support.v4.media.session.MediaSessionCompat} + now mirrors the functionality of {@link + android.media.session.MediaSession} and no longer calls {@link + android.media.session.MediaSession#setMediaButtonReceiver + setMediaButtonReceiver()} automatically + </li> + </ul> + <p class="note"> + <strong>Note:</strong> <a href= + "{@docRoot}reference/android/support/v4/media/MediaBrowserServiceCompat.html" + ><code>MediaBrowserServiceCompat</code></a> is compatible with + devices running API Level 24 as of Support Library revision 24.0.0. + Older versions of <a href= + "{@docRoot}reference/android/support/v4/media/MediaBrowserServiceCompat.html" + ><code>MediaBrowserServiceCompat</code></a> + are <em>not</em> compatible with API Level 24. If your app uses + <a href= + "{@docRoot}reference/android/support/v4/media/MediaBrowserServiceCompat.html" + ><code>MediaBrowserServiceCompat</code></a> and + supports devices running API level 24, you must update to Support + Library version 24.0.0 or later. + </p> + + <dt> + Changes for <a href= + "{@docRoot}tools/support-library/features.html#v7-appcompat">v7 + appcompat library</a>: + </dt> + + <dd> + <ul> + <li>Added support for referencing themed {@link + android.content.res.ColorStateList} objects from XML + </li> + </ul> + </dd> + + <dt> + Changes for <a href= + "{@docRoot}tools/support-library/features.html#design">Design Support + Library</a>: + </dt> + + <dd> + <ul> + <li>Improvements to {@link android.support.design.widget.AppBarLayout} + handling of elevation using {@link + android.animation.StateListAnimator} + </li> + </ul> + </dd> + + <dt> + Changes for <a href= + "{@docRoot}topic/libraries/support-library/features.html#v17-leanback" + >v17 Leanback library</a>: + </dt> + + <dd> + <ul> + <li>Added <code>OnboardingFragment</code> to provide first-run welcome + and setup flow + </li> + </ul> + </dd> + + <dt> + Changes for <a href= + "{@docRoot}topic/libraries/support-library/features.html#custom-tabs" + >custom tabs</a>: + </dt> + + <dd> + <ul> + <li>Added support for providing a {@link android.widget.RemoteViews} + hierarchy for the secondary toolbar</li> + <li>Added <code>CustomTabsClient.connectAndInitialize()</code> + for one-line warm up</li> + </ul> + </dd> + + </dl> + </div> +</div> + +<!-- end of collapsible section: 24.0.0 --> + + +<div class="toggle-content closed"> <p id="rev23-4-0"> <a href="#" onclick="return toggleContent(this)"><img src= "{@docRoot}assets/images/styles/disclosure_up.png" class= @@ -45,10 +163,9 @@ page.metaDescription=This page provides details about the Support Library packag <dd> <ul> - <li>Added <!-- TODO: Link to method --> - <code><a href= - "{@docRoot}reference/android/support/v7/app/AppCompatDelegate.html"> - AppCompatDelegate</a>.setCompatVectorFromResourcesEnabled()</code> + <li>Added + {@link android.support.v7.app.AppCompatDelegate#setCompatVectorFromResourcesEnabled + AppCompatDelegate.setCompatVectorFromResourcesEnabled()} method to re-enable usage of vector drawables in {@link android.graphics.drawable.DrawableContainer} objects on devices running Android 4.4 (API level 19) and lower. See <a href= @@ -118,8 +235,9 @@ page.metaDescription=This page provides details about the Support Library packag <dd> <ul> - <li>Fixed a bug where <!-- TODO: Javadoc link --> - <code>VectorDrawableCompat</code> does not render correctly in + <li>Fixed a bug where {@link + android.support.graphics.drawable.VectorDrawableCompat} does + not render correctly in {@link android.widget.TextView} on API level 23. (<a class= "external-link" href= "https://code.google.com/p/android/issues/detail?id=206227">Issue diff --git a/docs/html/training/material/compatibility.jd b/docs/html/training/material/compatibility.jd index 9ea88b2357b5..8ebe6f63cc39 100644 --- a/docs/html/training/material/compatibility.jd +++ b/docs/html/training/material/compatibility.jd @@ -127,7 +127,7 @@ the Android v7 Support Library with these limitations:</p> <p>To use these features in versions of Android earlier than 5.0 (API level 21), include the Android v7 Support Library in your project as a <a -href="{@docRoot}/studio/build/index.html#dependencies">Gradle dependency</a>:</p> +href="{@docRoot}studio/build/index.html#dependencies">Gradle dependency</a>:</p> <pre> dependencies { diff --git a/docs/html/training/wearables/watch-faces/performance.jd b/docs/html/training/wearables/watch-faces/performance.jd index 4a965456b173..a83a72b1f0f8 100644 --- a/docs/html/training/wearables/watch-faces/performance.jd +++ b/docs/html/training/wearables/watch-faces/performance.jd @@ -6,30 +6,117 @@ page.title=Optimizing Performance and Battery Life <div id="tb"> <h2>This lesson teaches you to</h2> <ol> + <li><a href="#Basic">Basic Optimization</a></li> + <li><a href="#Animations">Best Practices for Animations</a></li> <li><a href="#ReduceSize">Reduce the Size of Your Bitmap Assets</a></li> <li><a href="#CombineBitmaps">Combine Bitmap Assets</a></li> <li><a href="#AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</a></li> <li><a href="#OutDrawing">Move Expensive Operations Outside the Drawing Method</a></li> - <li><a href="#SavePower">Follow Best Practices to Save Power</a></li> </ol> <h2>You should also read</h2> <ul> <li><a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for Android Wear</a></li> <li><a href="http://android-developers.blogspot.com/2014/12/making-performant-watch-face.html"> Making a performant watch face</a></li> + <li><a href="http://android-developers.blogspot.com/2016/04/deprecation-of-bindlistener.html"> +Deprecation of BIND_LISTENER with Android Wear APIs</a></li> </ul> </div> </div> -<p>In addition to accommodating notification cards and system indicators, you need to ensure that -the animations in your watch face run smoothly and that your service does not perform unnecessary -computations. Watch faces in Android Wear run continuously on the device, so it is critical -that your watch face uses power efficiently.</p> +<p>This lesson has tips for conserving power and improving performance. +A watch face runs continuously, so it must use power +efficiently. </p> -<p>This lesson provides some tips to speed up your animations and to measure and conserve -power on the device.</p> +<p>Services must not perform unnecessary computations. +Watch faces with animations must run smoothly while accommodating +notification cards and system indicators.</p> +<h2 id="Basic">Basic Optimization</h2> +<p>This section contains best practices for improving efficiency during +periods when a watch face is inactive.</p> + +<h3>Use callbacks in WatchFaceService.Engine</h3> + +<p>Ensure that your watch face performs +computations only when active; use callbacks +in <a href="{@docRoot}reference/android/support/wearable/watchface/ +WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>. +Preferably, use the following methods of that class to determine if +the watch face is visible:</p> + +<ul> + <li>{@code onVisibilityChanged(boolean)}</li> + <li>{@code isVisible()}</li> +</ul> + +<p>Alternatively, use the following methods of the same class +(<a href="{@docRoot}reference/android/support/wearable/watchface/ +WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>):</p> + +<ul> + <li>{@code onCreate()}</li> + <li>{@code onDestroy()}</li> +</ul> + +<h3>Use listeners registered with the DataApi interface</h3> + +<p>To listen for events, use live listeners that are registered +with <a href="https://developers.google.com/android/reference/com/google/ +android/gms/wearable/DataApi.html#addListener +(com.google.android.gms.common.api.GoogleApiClient, com. +google.android.gms.wearable.DataApi.DataListener)">{@code DataApi.addListener}</a>. +For an example, see <a href="{@docRoot}training/wearables/data-layer/ +data-items.html#ListenEvents">Syncing Data Items</a>.</p> + +<p>Do not use <a href="https://developers.google.com/ +android/reference/com/google/android/gms/wearable/ +WearableListenerService">{@code WearableListenerService}</a> to listen for +events, because it is +called whether or not a watch face is active. For more information, see +<a href="http://android-developers.blogspot.com/2016/04/ +deprecation-of-bindlistener.html">Deprecation of BIND_LISTENER +with Android Wear APIs</a>.</p> + +<p>Do not register a broadcast receiver in the Android manifest file +to get system events such as time zone changes, battery events, etc., because +the <a href="{@docRoot}reference/android/content/BroadcastReceiver.html">{@code BroadcastReceiver}</a> +is called whether or not a watch face is active. However, you can use the +<a href="{@docRoot}reference/android/content/Context.html#registerReceiver(android. +content.BroadcastReceiver, android.content.IntentFilter)">{@code registerReceiver}</a> method +of the {@code Context} class to register a receiver.</p> + +<h3>Monitor power consumption</h3> + +<p>The <a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en"> +Android Wear companion app</a> enables developers and users to see how much battery +is consumed by different processes +on the wearable device (under <strong>Settings</strong> > <strong>Watch +battery</strong>).</p> + +<p>For information about features introduced in Android 5.0 that help you improve battery life, +see <a href="{@docRoot}about/versions/android-5.0.html#Power">Project Volta</a>.</p> + +<h2 id="Animations">Best Practices for Animations</h2> + +<p>The best practices in this section help to reduce the power consumption of animations.</p> + +<h3>Reduce the frame rate of animations</h3> + +<p>Animations are often computationally expensive and consume a significant amount of power. Most +animations look fluid at 30 frames per second, so you should avoid running your animations +at a higher frame rate.</p> + +<h3>Let the CPU sleep between animations</h3> + +<p>Animations and small changes to the contents of the watch face wake up the CPU. Your watch +face should let the CPU sleep in between animations. For example, you can use short bursts of +animation every second in interactive mode and then let the CPU sleep until the next second. +Letting the CPU sleep often, even briefly, can significantly reduce power consumption.</p> + +<p>To maximize battery life, use animations sparingly. Even a blinking colon wakes up the CPU with +every blink and hurts battery life.</p> <h2 id="ReduceSize">Reduce the Size of Your Bitmap Assets</h2> @@ -68,16 +155,12 @@ by 97%.</p> <p>Reducing the size of your bitmap assets as described in this section not only improves the performance of your animations, but it also saves power.</p> - - <h2 id="CombineBitmaps">Combine Bitmap Assets</h2> <p>If you have bitmaps that are often drawn together, consider combining them into the same graphic asset. You can often combine the background image in interactive mode with the tick marks to avoid drawing two full-screen bitmaps every time the system redraws the watch face.</p> - - <h2 id="AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</h2> <p>When you draw a scaled bitmap on the {@link android.graphics.Canvas} object using the {@link @@ -139,35 +222,3 @@ implementation is short and consistent across invocations. For more information, see <a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a>.</p> - - -<h2 id="SavePower">Follow Best Practices to Save Power</h2> - -<p>In addition to the techniques described in the previous sections, follow the best -practices in this section to reduce the power consumption of your watch face.</p> - -<h3>Reduce the frame rate of animations</h3> - -<p>Animations are often computationally expensive and consume a significant amount of power. Most -animations look fluid at 30 frames per second, so you should avoid running your animations -at a higher frame rate.</p> - -<h3>Let the CPU sleep</h3> - -<p>Animations and small changes to the contents of the watch face wake up the CPU. Your watch -face should let the CPU sleep in between animations. For example, you can use short bursts of -animation every second in interactive mode and then let the CPU sleep until the next second. -Letting the CPU sleep often, even briefly, can significantly reduce power consumption.</p> - -<p>To maximize battery life, use animations sparingly. Even a blinking colon wakes up the CPU with -every blink and hurts battery life.</p> - -<h3>Monitor power consumption</h3> - -<p>The <a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en"> -Android Wear companion app</a> lets developers and users see how much battery different processes -on the wearable device are consuming under <strong>Settings</strong> > <strong>Watch -battery</strong>.</p> - -<p>For more information about new features in Android 5.0 that help you improve battery life, -see <a href="{@docRoot}about/versions/android-5.0.html#Power">Project Volta</a>.</p> diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index e6399d4ec789..c626c5452310 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -149,6 +149,8 @@ void CanvasContext::setStopped(bool stopped) { if (mEglManager.isCurrent(mEglSurface)) { mEglManager.makeCurrent(EGL_NO_SURFACE); } + } else if (mIsDirty && hasSurface()) { + mRenderThread.postFrameCallback(this); } } } @@ -231,6 +233,8 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, freePrefetchedLayers(info.observer); GL_CHECKPOINT(MODERATE); + mIsDirty = true; + if (CC_UNLIKELY(!mNativeSurface.get())) { mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame); info.out.canDrawThisFrame = false; @@ -503,6 +507,7 @@ void CanvasContext::draw() { // Even if we decided to cancel the frame, from the perspective of jank // metrics the frame was swapped at this point mCurrentFrameInfo->markSwapBuffers(); + mIsDirty = false; if (drew || mEglManager.damageRequiresSwap()) { if (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty))) { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index e739b2949cf9..a6eb7adc3568 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -187,7 +187,12 @@ private: EglManager& mEglManager; sp<Surface> mNativeSurface; EGLSurface mEglSurface = EGL_NO_SURFACE; + // stopped indicates the CanvasContext will reject actual redraw operations, + // and defer repaint until it is un-stopped bool mStopped = false; + // CanvasContext is dirty if it has received an update that it has not + // painted onto its surface. + bool mIsDirty = false; bool mBufferPreserved = false; SwapBehavior mSwapBehavior = kSwap_default; struct SwapHistory { diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 3f6081bf183d..4d40e6ba99ab 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -709,6 +709,8 @@ public class MediaPlayer extends PlayerBase * played. * * @param sh the SurfaceHolder to use for video display + * @throws IllegalStateException if the internal player engine has not been + * initialized or has been released. */ public void setDisplay(SurfaceHolder sh) { mSurfaceHolder = sh; @@ -739,6 +741,8 @@ public class MediaPlayer extends PlayerBase * * @param surface The {@link Surface} to be used for the video portion of * the media. + * @throws IllegalStateException if the internal player engine has not been + * initialized or has been released. */ public void setSurface(Surface surface) { if (mScreenOnWhilePlaying && surface != null) { diff --git a/packages/PrintRecommendationService/AndroidManifest.xml b/packages/PrintRecommendationService/AndroidManifest.xml index 0eb218c853ec..c6736d7bac23 100644 --- a/packages/PrintRecommendationService/AndroidManifest.xml +++ b/packages/PrintRecommendationService/AndroidManifest.xml @@ -17,7 +17,12 @@ */ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.printservice.recommendation"> + package="com.android.printservice.recommendation" + android:versionCode="1" + android:versionName="1.0.0"> + + <uses-sdk android:minSdkVersion="24" + android:targetSdkVersion="24" /> <uses-permission android:name="android.permission.INTERNET" /> diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index e071f6a07170..284827b57929 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -28,13 +28,10 @@ import android.support.v7.preference.PreferenceViewHolder; import android.text.TextUtils; import android.util.AttributeSet; import android.util.SparseArray; -import android.view.View; import android.widget.TextView; import com.android.settingslib.R; -import java.util.Objects; - public class AccessPointPreference extends Preference { private static final int[] STATE_SECURED = { @@ -111,7 +108,6 @@ public class AccessPointPreference extends Preference { mTitleView.setCompoundDrawablePadding(mBadgePadding); } view.itemView.setContentDescription(mContentDescription); - view.itemView.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE); } protected void updateIcon(int level, Context context) { @@ -152,7 +148,6 @@ public class AccessPointPreference extends Preference { * Updates the title and summary; may indirectly call notifyChanged(). */ public void refresh() { - boolean updated = false; if (mForSavedNetworks) { setTitle(mAccessPoint.getConfigName()); } else { @@ -164,28 +159,21 @@ public class AccessPointPreference extends Preference { if (level != mLevel) { mLevel = level; updateIcon(mLevel, context); - updated = true; + notifyChanged(); } updateBadge(context); setSummary(mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary() : mAccessPoint.getSettingsSummary()); - CharSequence contentDescription = getTitle(); + mContentDescription = getTitle(); if (getSummary() != null) { - contentDescription = TextUtils.concat(contentDescription, ",", getSummary()); + mContentDescription = TextUtils.concat(mContentDescription, ",", getSummary()); } if (level >= 0 && level < WIFI_CONNECTION_STRENGTH.length) { - contentDescription = TextUtils.concat(contentDescription, ",", + mContentDescription = TextUtils.concat(mContentDescription, ",", getContext().getString(WIFI_CONNECTION_STRENGTH[level])); } - if (!Objects.equals(contentDescription, mContentDescription)) { - mContentDescription = contentDescription; - updated = true; - } - if (updated) { - notifyChanged(); - } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index 9fb8bd557b90..2c5c437bfab0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -34,6 +34,7 @@ import android.util.IntProperty; import android.util.Property; import android.util.TypedValue; import android.view.View; +import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewStub; @@ -285,6 +286,26 @@ public class Utilities { } /** + * Returns whether this view, or one of its descendants have accessibility focus. + */ + public static boolean isDescendentAccessibilityFocused(View v) { + if (v.isAccessibilityFocused()) { + return true; + } + + if (v instanceof ViewGroup) { + ViewGroup vg = (ViewGroup) v; + int childCount = vg.getChildCount(); + for (int i = 0; i < childCount; i++) { + if (isDescendentAccessibilityFocused(vg.getChildAt(i))) { + return true; + } + } + } + return false; + } + + /** * Returns the application configuration, which is independent of the activity's current * configuration in multiwindow. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 231360e46ae9..586a8bcd8920 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -44,6 +44,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; +import android.widget.ScrollView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; @@ -170,7 +171,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @ViewDebug.ExportedProperty(category="recents") private boolean mEnterAnimationComplete = false; @ViewDebug.ExportedProperty(category="recents") - private boolean mTouchExplorationEnabled; + boolean mTouchExplorationEnabled; @ViewDebug.ExportedProperty(category="recents") boolean mScreenPinningEnabled; @@ -579,7 +580,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (task.isFreeformTask() || (transform != null && transform.visible)) { mTmpTaskViewMap.put(task.key, tv); } else { - if (mTouchExplorationEnabled) { + if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) { lastFocusedTaskIndex = taskIndex; resetFocusedTask(task); } @@ -630,12 +631,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Update the focus if the previous focused task was returned to the view pool if (lastFocusedTaskIndex != -1) { - if (lastFocusedTaskIndex < visibleTaskRange[1]) { - setFocusedTask(visibleTaskRange[1], false /* scrollToTask */, - true /* requestViewFocus */); - } else { - setFocusedTask(visibleTaskRange[0], false /* scrollToTask */, - true /* requestViewFocus */); + int newFocusedTaskIndex = (lastFocusedTaskIndex < visibleTaskRange[1]) + ? visibleTaskRange[1] + : visibleTaskRange[0]; + setFocusedTask(newFocusedTaskIndex, false /* scrollToTask */, + true /* requestViewFocus */); + TaskView focusedTaskView = getChildViewForTask(mFocusedTask); + if (focusedTaskView != null) { + focusedTaskView.requestAccessibilityFocus(); } } } @@ -938,24 +941,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * focus. */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) { - setRelativeFocusedTask(forward, stackTasksOnly, animated, false); - } - - /** - * Sets the focused task relative to the currently focused task. - * - * @param forward whether to go to the next task in the stack (along the curve) or the previous - * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and - * if the currently focused task is not a stack task, will set the focus - * to the first visible stack task - * @param animated determines whether to actually draw the highlight along with the change in - * focus. - * @param cancelWindowAnimations if set, will attempt to cancel window animations if a scroll - * happens. - */ - public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated, - boolean cancelWindowAnimations) { - setRelativeFocusedTask(forward, stackTasksOnly, animated, cancelWindowAnimations, 0); + setRelativeFocusedTask(forward, stackTasksOnly, animated, false, 0); } /** @@ -972,13 +958,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated, - boolean cancelWindowAnimations, - int timerIndicatorDuration) { - int newIndex = mStack.indexOfStackTask(mFocusedTask); - if (mFocusedTask != null) { + boolean cancelWindowAnimations, int timerIndicatorDuration) { + Task focusedTask = getFocusedTask(); + int newIndex = mStack.indexOfStackTask(focusedTask); + if (focusedTask != null) { if (stackTasksOnly) { List<Task> tasks = mStack.getStackTasks(); - if (mFocusedTask.isFreeformTask()) { + if (focusedTask.isFreeformTask()) { // Try and focus the front most stack task TaskView tv = getFrontMostTaskView(stackTasksOnly); if (tv != null) { @@ -1054,6 +1040,25 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal return mFocusedTask; } + /** + * Returns the accessibility focused task. + */ + Task getAccessibilityFocusedTask() { + List<TaskView> taskViews = getTaskViews(); + int taskViewCount = taskViews.size(); + for (int i = 0; i < taskViewCount; i++) { + TaskView tv = taskViews.get(i); + if (Utilities.isDescendentAccessibilityFocused(tv)) { + return tv.getTask(); + } + } + TaskView frontTv = getFrontMostTaskView(true /* stackTasksOnly */); + if (frontTv != null) { + return frontTv.getTask(); + } + return null; + } + @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); @@ -1078,21 +1083,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal super.onInitializeAccessibilityNodeInfo(info); List<TaskView> taskViews = getTaskViews(); int taskViewCount = taskViews.size(); - if (taskViewCount > 1 && mFocusedTask != null) { + if (taskViewCount > 1) { + // Find the accessibility focused task + Task focusedTask = getAccessibilityFocusedTask(); info.setScrollable(true); - int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask); + int focusedTaskIndex = mStack.indexOfStackTask(focusedTask); if (focusedTaskIndex > 0) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); - } - if (focusedTaskIndex < mStack.getTaskCount() - 1) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); } + if (0 <= focusedTaskIndex && focusedTaskIndex < mStack.getTaskCount() - 1) { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + } } } @Override public CharSequence getAccessibilityClassName() { - return TaskStackView.class.getName(); + return ScrollView.class.getName(); } @Override @@ -1100,14 +1107,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (super.performAccessibilityAction(action, arguments)) { return true; } - switch (action) { - case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { - setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */); - return true; - } - case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { - setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */); - return true; + Task focusedTask = getAccessibilityFocusedTask(); + int taskIndex = mStack.indexOfStackTask(focusedTask); + if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) { + switch (action) { + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + setFocusedTask(taskIndex + 1, true /* scrollToTask */, true /* requestViewFocus */, + 0); + return true; + } + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + setFocusedTask(taskIndex - 1, true /* scrollToTask */, true /* requestViewFocus */, + 0); + return true; + } } } return false; @@ -1489,6 +1502,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal unbindTaskView(tv, task); // Reset the view properties and view state + tv.clearAccessibilityFocus(); tv.resetViewProperties(); tv.setFocusedState(false, false /* requestViewFocus */); tv.setClipViewInStack(false); @@ -1949,6 +1963,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal RecentsActivityLaunchState launchState = config.getLaunchState(); setFocusedTask(mStack.indexOfStackTask(mFocusedTask), false /* scrollToTask */, launchState.launchedWithAltTab); + TaskView focusedTaskView = getChildViewForTask(mFocusedTask); + if (mTouchExplorationEnabled && focusedTaskView != null) { + focusedTaskView.requestAccessibilityFocus(); + } } EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java index b554a467c7ce..67a2595c90cd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -343,7 +343,9 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { } // Reset the focused task after the user has scrolled - mSv.resetFocusedTask(mSv.getFocusedTask()); + if (!mSv.mTouchExplorationEnabled) { + mSv.resetFocusedTask(mSv.getFocusedTask()); + } } else if (mActiveTaskView == null) { // This tap didn't start on a task. maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 612c41d07a04..4ecdd7788001 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -133,8 +133,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @ViewDebug.ExportedProperty(deepExport=true, prefix="task_") private Task mTask; @ViewDebug.ExportedProperty(category="recents") - private boolean mTaskDataLoaded; - @ViewDebug.ExportedProperty(category="recents") private boolean mClipViewInStack = true; @ViewDebug.ExportedProperty(category="recents") private boolean mTouchExplorationEnabled; @@ -451,16 +449,12 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks * Explicitly sets the focused state of this task. */ public void setFocusedState(boolean isFocused, boolean requestViewFocus) { - SystemServicesProxy ssp = Recents.getSystemServices(); if (isFocused) { if (requestViewFocus && !isFocused()) { requestFocus(); } - if (requestViewFocus && !isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { - requestAccessibilityFocus(); - } } else { - if (isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { + if (isAccessibilityFocused() && mTouchExplorationEnabled) { clearAccessibilityFocus(); } } @@ -622,7 +616,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks // Update each of the views to the new task data mThumbnailView.onTaskDataLoaded(thumbnailInfo); mHeaderView.onTaskDataLoaded(); - mTaskDataLoaded = true; } @Override @@ -631,7 +624,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mTask.removeCallback(this); mThumbnailView.unbindFromTask(); mHeaderView.unbindFromTask(mTouchExplorationEnabled); - mTaskDataLoaded = false; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index aedc7df0ebc3..28a6851307fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -193,6 +193,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { mGroupExpansionChanging = changing; } + @Override + public void setActualHeightAnimating(boolean animating) { + if (mPrivateLayout != null) { + mPrivateLayout.setContentHeightAnimating(animating); + } + } + public NotificationContentView getPrivateLayout() { return mPrivateLayout; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java index 2c302ed1af4e..b4f90c60b84e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java @@ -432,6 +432,8 @@ public abstract class ExpandableView extends FrameLayout { return false; } + public void setActualHeightAnimating(boolean animating) {} + /** * A listener notifying when {@link #getActualHeight} changes. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 21fed3c47689..a11263a3b9f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -106,13 +106,19 @@ public class NotificationContentView extends FrameLayout { private boolean mExpandable; private boolean mClipToActualHeight = true; private ExpandableNotificationRow mContainingNotification; + /** The visible type at the start of a touch driven transformation */ private int mTransformationStartVisibleType; + /** The visible type at the start of an animation driven transformation */ + private int mAnimationStartVisibleType = UNDEFINED; private boolean mUserExpanding; private int mSingleLineWidthIndention; private boolean mForceSelectNextLayout = true; private PendingIntent mPreviousExpandedRemoteInputIntent; private PendingIntent mPreviousHeadsUpRemoteInputIntent; + private int mContentHeightAtAnimationStart = UNDEFINED; + + public NotificationContentView(Context context, AttributeSet attrs) { super(context, attrs); mHybridGroupManager = new HybridGroupManager(getContext(), this); @@ -258,7 +264,14 @@ public class NotificationContentView extends FrameLayout { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int previousHeight = 0; + if (mExpandedChild != null) { + previousHeight = mExpandedChild.getHeight(); + } super.onLayout(changed, left, top, right, bottom); + if (previousHeight != 0 && mExpandedChild.getHeight() != previousHeight) { + mContentHeightAtAnimationStart = previousHeight; + } updateClipping(); invalidateOutline(); selectLayout(false /* animate */, mForceSelectNextLayout /* force */); @@ -408,24 +421,54 @@ public class NotificationContentView extends FrameLayout { * height, the notification is clipped instead of being further shrunk. */ private int getMinContentHeightHint() { - if (mIsChildInGroup && (mVisibleType == VISIBLE_TYPE_SINGLELINE - || mTransformationStartVisibleType == VISIBLE_TYPE_SINGLELINE)) { + if (mIsChildInGroup && isVisibleOrTransitioning(VISIBLE_TYPE_SINGLELINE)) { return mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.notification_action_list_height); } + + // Transition between heads-up & expanded, or pinned. + if (mHeadsUpChild != null && mExpandedChild != null) { + boolean transitioningBetweenHunAndExpanded = + isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) || + isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP); + boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED) && mIsHeadsUp; + if (transitioningBetweenHunAndExpanded || pinned) { + return Math.min(mHeadsUpChild.getHeight(), mExpandedChild.getHeight()); + } + } + + // Size change of the expanded version + if ((mVisibleType == VISIBLE_TYPE_EXPANDED) && mContentHeightAtAnimationStart >= 0 + && mExpandedChild != null) { + return Math.min(mContentHeightAtAnimationStart, mExpandedChild.getHeight()); + } + int hint; - if (mHeadsUpChild != null) { + if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) { hint = mHeadsUpChild.getHeight(); + } else if (mExpandedChild != null) { + hint = mExpandedChild.getHeight(); } else { hint = mContractedChild.getHeight() + mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.notification_action_list_height); } - if (mExpandedChild != null) { + + if (mExpandedChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_EXPANDED)) { hint = Math.min(hint, mExpandedChild.getHeight()); } return hint; } + private boolean isTransitioningFromTo(int from, int to) { + return (mTransformationStartVisibleType == from || mAnimationStartVisibleType == from) + && mVisibleType == to; + } + + private boolean isVisibleOrTransitioning(int type) { + return mVisibleType == type || mTransformationStartVisibleType == type + || mAnimationStartVisibleType == type; + } + private void updateContentTransformation() { int visibleType = calculateVisibleType(); if (visibleType != mVisibleType) { @@ -656,6 +699,7 @@ public class NotificationContentView extends FrameLayout { shownView.setVisible(true); return; } + mAnimationStartVisibleType = mVisibleType; shownView.transformFrom(hiddenView); getViewForVisibleType(visibleType).setVisibility(View.VISIBLE); hiddenView.transformTo(shownView, new Runnable() { @@ -664,6 +708,7 @@ public class NotificationContentView extends FrameLayout { if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) { hiddenView.setVisible(false); } + mAnimationStartVisibleType = UNDEFINED; } }); } @@ -1082,4 +1127,10 @@ public class NotificationContentView extends FrameLayout { mHeadsUpRemoteInput.setRemoved(); } } + + public void setContentHeightAnimating(boolean animating) { + if (!animating) { + mContentHeightAtAnimationStart = UNDEFINED; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java index c0373bef0f5a..8c725446a3cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java @@ -44,6 +44,16 @@ public class ActionListTransformState extends TransformState { } @Override + public void transformViewFullyFrom(TransformState otherState, float transformationAmount) { + // Don't do Y transform - let the wrapper handle this based on the content height + } + + @Override + public void transformViewFullyTo(TransformState otherState, float transformationAmount) { + // Don't do Y transform - let the wrapper handle this based on the content height + } + + @Override protected void resetTransformedView() { // We need to keep the Y transformation, because this is used to keep the action list // aligned at the bottom, unrelated to transforms. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java index 0f94227c6184..7ac0d803e24e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -485,6 +485,7 @@ public class StackStateAnimator { child.setTag(TAG_ANIMATOR_HEIGHT, null); child.setTag(TAG_START_HEIGHT, null); child.setTag(TAG_END_HEIGHT, null); + child.setActualHeightAnimating(false); if (!mWasCancelled && child instanceof ExpandableNotificationRow) { ((ExpandableNotificationRow) child).setGroupExpansionChanging( false /* isExpansionChanging */); @@ -505,6 +506,7 @@ public class StackStateAnimator { child.setTag(TAG_ANIMATOR_HEIGHT, animator); child.setTag(TAG_START_HEIGHT, child.getActualHeight()); child.setTag(TAG_END_HEIGHT, newEndValue); + child.setActualHeightAnimating(true); } private void startInsetAnimation(final ExpandableView child, diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java index c6992aad068e..1973e058e3e9 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java @@ -977,6 +977,7 @@ public class VolumeDialog implements TunerService.Tunable { final int density = newConfig.densityDpi; if (density != mDensity) { mDialog.dismiss(); + mZenFooter.cleanup(); initDialog(); } updateWindowWidthH(); diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java index 65975d9e9f33..f01e95fa3873 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java @@ -79,18 +79,11 @@ public class ZenFooter extends LinearLayout { mZen = controller.getZen(); mConfig = controller.getConfig(); mController = controller; - update(); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); mController.addCallback(mZenCallback); + update(); } - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); + public void cleanup() { mController.removeCallback(mZenCallback); } diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 8ad6e6afcce5..400c4a700a8e 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -3073,9 +3073,14 @@ class AlarmManagerService extends SystemService { fs.numWakeup++; if (alarm.workSource != null && alarm.workSource.size() > 0) { for (int wi=0; wi<alarm.workSource.size(); wi++) { + final String wsName = alarm.workSource.getName(wi); + if (wsName == null) { + Slog.w(TAG, "Null worksource name for alarm " + alarm); + } ActivityManagerNative.noteWakeupAlarm( alarm.operation, alarm.workSource.get(wi), - alarm.workSource.getName(wi), alarm.statsTag); + (wsName != null) ? wsName : alarm.packageName, + alarm.statsTag); } } else { ActivityManagerNative.noteWakeupAlarm( diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index df85cfa939e3..d83a750ccbb3 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2581,14 +2581,11 @@ final class ActivityStack { } private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) { - boolean isLastTaskOverHome = false; // If the moving task is over home stack, transfer its return type to next task if (task.isOverHomeStack()) { final TaskRecord nextTask = getNextTask(task); if (nextTask != null) { nextTask.setTaskToReturnTo(task.getTaskToReturnTo()); - } else { - isLastTaskOverHome = true; } } @@ -2598,10 +2595,7 @@ final class ActivityStack { ActivityStack lastStack = mStackSupervisor.getLastStack(); final boolean fromHome = lastStack.isHomeStack(); if (!isHomeStack() && (fromHome || topTask() != task)) { - // If it's a last task over home - we default to keep its return to type not to - // make underlying task focused when this one will be finished. - int returnToType = isLastTaskOverHome - ? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE; + int returnToType = APPLICATION_ACTIVITY_TYPE; if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) { returnToType = lastStack.topTask() == null ? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType; diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java index 566d8d95d952..a2c2040b5c51 100644 --- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java +++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java @@ -147,6 +147,9 @@ class ActivityStartInterceptor { } DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( DevicePolicyManagerInternal.class); + if (devicePolicyManager == null) { + return false; + } mIntent = devicePolicyManager.createPackageSuspendedDialogIntent( mAInfo.packageName, mUserId); mCallingPid = mRealCallingPid; diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 1b2ccd7e43ad..9220aa388f3e 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AppOpsManager; +import android.app.job.JobInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; @@ -512,6 +513,16 @@ public final class ContentService extends IContentService.Stub { syncAsUser(request, UserHandle.getCallingUserId()); } + private long clampPeriod(long period) { + long minPeriod = JobInfo.getMinPeriodMillis() / 1000; + if (period < minPeriod) { + Slog.w(TAG, "Requested poll frequency of " + period + + " seconds being rounded up to " + minPeriod + "s."); + period = minPeriod; + } + return period; + } + /** * If the user id supplied is different to the calling user, the caller must hold the * INTERACT_ACROSS_USERS_FULL permission. @@ -539,11 +550,8 @@ public final class ContentService extends IContentService.Stub { SyncStorageEngine.EndPoint info; info = new SyncStorageEngine.EndPoint( request.getAccount(), request.getProvider(), userId); - if (runAtTime < 3600) { - Slog.w(TAG, "Requested poll frequency of " + runAtTime - + " seconds being rounded up to 1 hour."); - runAtTime = 3600; - } + + runAtTime = clampPeriod(runAtTime); // Schedule periodic sync. getSyncManager().updateOrAddPeriodicSync(info, runAtTime, flextime, extras); @@ -761,11 +769,8 @@ public final class ContentService extends IContentService.Stub { "no permission to write the sync settings"); int userId = UserHandle.getCallingUserId(); - if (pollFrequency < 3600) { - Slog.w(TAG, "Requested poll frequency of " + pollFrequency - + " seconds being rounded up to 1 hour."); - pollFrequency = 3600; - } + + pollFrequency = clampPeriod(pollFrequency); long defaultFlex = SyncStorageEngine.calculateDefaultFlexTime(pollFrequency); long identityToken = clearCallingIdentity(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 4692a57406d1..b5280165bb39 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8139,21 +8139,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); intent.putExtra(Intent.EXTRA_USER_ID, userId); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - synchronized (DevicePolicyManagerService.this) { - ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); - if (profileOwner != null) { - intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner); - return intent; - } - if (mOwners.getDeviceOwnerUserId() == userId) { - ComponentName deviceOwner = mOwners.getDeviceOwnerComponent(); - if (deviceOwner != null) { - intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner); - return intent; - } - } + // This method is called from AM with its lock held, so don't take the DPMS lock. + // b/29242568 + + ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); + if (profileOwner != null) { + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner); + return intent; + } + + final Pair<Integer, ComponentName> deviceOwner = + mOwners.getDeviceOwnerUserIdAndComponent(); + if (deviceOwner != null && deviceOwner.first == userId) { + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner.second); + return intent; } + // We're not specifying the device admin because there isn't one. return intent; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java index cb39ebd0e3b0..1ae1a773b23e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java @@ -16,9 +16,9 @@ package com.android.server.devicepolicy; +import android.annotation.Nullable; import android.app.admin.SystemUpdatePolicy; import android.content.ComponentName; -import android.content.Context; import android.content.pm.PackageManagerInternal; import android.content.pm.UserInfo; import android.os.Environment; @@ -28,6 +28,7 @@ import android.os.UserManagerInternal; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Log; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.Xml; @@ -54,8 +55,8 @@ import libcore.io.IoUtils; * Stores and restores state for the Device and Profile owners. By definition there can be * only one device owner, but there may be a profile owner for each user. * - * <p>This class is not thread safe. (i.e. access to this class must always be synchronized - * in the caller side.) + * <p>This class is thread safe, so individual methods can safely be called without locking. + * However, caller must still synchronize on their side to ensure integrity between multiple calls. */ class Owners { private static final String TAG = "DevicePolicyManagerService"; @@ -101,6 +102,8 @@ class Owners { // Local system update policy controllable by device owner. private SystemUpdatePolicy mSystemUpdatePolicy; + private final Object mLock = new Object(); + public Owners(UserManager userManager, UserManagerInternal userManagerInternal, PackageManagerInternal packageManagerInternal) { @@ -113,47 +116,49 @@ class Owners { * Load configuration from the disk. */ void load() { - // First, try to read from the legacy file. - final File legacy = getLegacyConfigFileWithTestOverride(); + synchronized (mLock) { + // First, try to read from the legacy file. + final File legacy = getLegacyConfigFileWithTestOverride(); - final List<UserInfo> users = mUserManager.getUsers(); + final List<UserInfo> users = mUserManager.getUsers(); - if (readLegacyOwnerFile(legacy)) { - if (DEBUG) { - Log.d(TAG, "Legacy config file found."); - } + if (readLegacyOwnerFileLocked(legacy)) { + if (DEBUG) { + Log.d(TAG, "Legacy config file found."); + } - // Legacy file exists, write to new files and remove the legacy one. - writeDeviceOwner(); - for (int userId : getProfileOwnerKeys()) { - writeProfileOwner(userId); - } - if (DEBUG) { - Log.d(TAG, "Deleting legacy config file"); - } - if (!legacy.delete()) { - Slog.e(TAG, "Failed to remove the legacy setting file"); - } - } else { - // No legacy file, read from the new format files. - new DeviceOwnerReadWriter().readFromFileLocked(); + // Legacy file exists, write to new files and remove the legacy one. + writeDeviceOwner(); + for (int userId : getProfileOwnerKeys()) { + writeProfileOwner(userId); + } + if (DEBUG) { + Log.d(TAG, "Deleting legacy config file"); + } + if (!legacy.delete()) { + Slog.e(TAG, "Failed to remove the legacy setting file"); + } + } else { + // No legacy file, read from the new format files. + new DeviceOwnerReadWriter().readFromFileLocked(); + for (UserInfo ui : users) { + new ProfileOwnerReadWriter(ui.id).readFromFileLocked(); + } + } + mUserManagerInternal.setDeviceManaged(hasDeviceOwner()); for (UserInfo ui : users) { - new ProfileOwnerReadWriter(ui.id).readFromFileLocked(); + mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id)); } + if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) { + Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported", + getDeviceOwnerUserId())); + } + pushToPackageManagerLocked(); } - mUserManagerInternal.setDeviceManaged(hasDeviceOwner()); - for (UserInfo ui : users) { - mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id)); - } - if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) { - Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported", - getDeviceOwnerUserId())); - } - pushToPackageManager(); } - private void pushToPackageManager() { + private void pushToPackageManagerLocked() { final SparseArray<String> po = new SparseArray<>(); for (int i = mProfileOwners.size() - 1; i >= 0; i--) { po.put(mProfileOwners.keyAt(i), mProfileOwners.valueAt(i).packageName); @@ -164,27 +169,50 @@ class Owners { } String getDeviceOwnerPackageName() { - return mDeviceOwner != null ? mDeviceOwner.packageName : null; + synchronized (mLock) { + return mDeviceOwner != null ? mDeviceOwner.packageName : null; + } } int getDeviceOwnerUserId() { - return mDeviceOwnerUserId; + synchronized (mLock) { + return mDeviceOwnerUserId; + } + } + + @Nullable + Pair<Integer, ComponentName> getDeviceOwnerUserIdAndComponent() { + synchronized (mLock) { + if (mDeviceOwner == null) { + return null; + } else { + return Pair.create(mDeviceOwnerUserId, mDeviceOwner.admin); + } + } } String getDeviceOwnerName() { - return mDeviceOwner != null ? mDeviceOwner.name : null; + synchronized (mLock) { + return mDeviceOwner != null ? mDeviceOwner.name : null; + } } ComponentName getDeviceOwnerComponent() { - return mDeviceOwner != null ? mDeviceOwner.admin : null; + synchronized (mLock) { + return mDeviceOwner != null ? mDeviceOwner.admin : null; + } } String getDeviceOwnerRemoteBugreportUri() { - return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null; + synchronized (mLock) { + return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null; + } } String getDeviceOwnerRemoteBugreportHash() { - return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null; + synchronized (mLock) { + return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null; + } } void setDeviceOwner(ComponentName admin, String ownerName, int userId) { @@ -192,132 +220,172 @@ class Owners { Slog.e(TAG, "Invalid user id for device owner user: " + userId); return; } - // For a newly set DO, there's no need for migration. - setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId, - /* userRestrictionsMigrated =*/ true); + synchronized (mLock) { + // For a newly set DO, there's no need for migration. + setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId, + /* userRestrictionsMigrated =*/ true); + } } // Note this should be only called during migration. Normally when DO is set, // userRestrictionsMigrated should always be true. void setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId, boolean userRestrictionsMigrated) { - mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated, - /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null); - mDeviceOwnerUserId = userId; + synchronized (mLock) { + mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated, + /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null); + mDeviceOwnerUserId = userId; - mUserManagerInternal.setDeviceManaged(true); - pushToPackageManager(); + mUserManagerInternal.setDeviceManaged(true); + pushToPackageManagerLocked(); + } } void clearDeviceOwner() { - mDeviceOwner = null; - mDeviceOwnerUserId = UserHandle.USER_NULL; + synchronized (mLock) { + mDeviceOwner = null; + mDeviceOwnerUserId = UserHandle.USER_NULL; - mUserManagerInternal.setDeviceManaged(false); - pushToPackageManager(); + mUserManagerInternal.setDeviceManaged(false); + pushToPackageManagerLocked(); + } } void setProfileOwner(ComponentName admin, String ownerName, int userId) { - // For a newly set PO, there's no need for migration. - mProfileOwners.put(userId, new OwnerInfo(ownerName, admin, - /* userRestrictionsMigrated =*/ true, /* remoteBugreportUri =*/ null, - /* remoteBugreportHash =*/ null)); - mUserManagerInternal.setUserManaged(userId, true); - pushToPackageManager(); + synchronized (mLock) { + // For a newly set PO, there's no need for migration. + mProfileOwners.put(userId, new OwnerInfo(ownerName, admin, + /* userRestrictionsMigrated =*/ true, /* remoteBugreportUri =*/ null, + /* remoteBugreportHash =*/ null)); + mUserManagerInternal.setUserManaged(userId, true); + pushToPackageManagerLocked(); + } } void removeProfileOwner(int userId) { - mProfileOwners.remove(userId); - mUserManagerInternal.setUserManaged(userId, false); - pushToPackageManager(); + synchronized (mLock) { + mProfileOwners.remove(userId); + mUserManagerInternal.setUserManaged(userId, false); + pushToPackageManagerLocked(); + } } ComponentName getProfileOwnerComponent(int userId) { - OwnerInfo profileOwner = mProfileOwners.get(userId); - return profileOwner != null ? profileOwner.admin : null; + synchronized (mLock) { + OwnerInfo profileOwner = mProfileOwners.get(userId); + return profileOwner != null ? profileOwner.admin : null; + } } String getProfileOwnerName(int userId) { - OwnerInfo profileOwner = mProfileOwners.get(userId); - return profileOwner != null ? profileOwner.name : null; + synchronized (mLock) { + OwnerInfo profileOwner = mProfileOwners.get(userId); + return profileOwner != null ? profileOwner.name : null; + } } String getProfileOwnerPackage(int userId) { - OwnerInfo profileOwner = mProfileOwners.get(userId); - return profileOwner != null ? profileOwner.packageName : null; + synchronized (mLock) { + OwnerInfo profileOwner = mProfileOwners.get(userId); + return profileOwner != null ? profileOwner.packageName : null; + } } Set<Integer> getProfileOwnerKeys() { - return mProfileOwners.keySet(); + synchronized (mLock) { + return mProfileOwners.keySet(); + } } SystemUpdatePolicy getSystemUpdatePolicy() { - return mSystemUpdatePolicy; + synchronized (mLock) { + return mSystemUpdatePolicy; + } } void setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy) { - mSystemUpdatePolicy = systemUpdatePolicy; + synchronized (mLock) { + mSystemUpdatePolicy = systemUpdatePolicy; + } } void clearSystemUpdatePolicy() { - mSystemUpdatePolicy = null; + synchronized (mLock) { + mSystemUpdatePolicy = null; + } } boolean hasDeviceOwner() { - return mDeviceOwner != null; + synchronized (mLock) { + return mDeviceOwner != null; + } } boolean isDeviceOwnerUserId(int userId) { - return mDeviceOwner != null && mDeviceOwnerUserId == userId; + synchronized (mLock) { + return mDeviceOwner != null && mDeviceOwnerUserId == userId; + } } boolean hasProfileOwner(int userId) { - return getProfileOwnerComponent(userId) != null; + synchronized (mLock) { + return getProfileOwnerComponent(userId) != null; + } } /** * @return true if user restrictions need to be migrated for DO. */ boolean getDeviceOwnerUserRestrictionsNeedsMigration() { - return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated; + synchronized (mLock) { + return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated; + } } /** * @return true if user restrictions need to be migrated for PO. */ boolean getProfileOwnerUserRestrictionsNeedsMigration(int userId) { - OwnerInfo profileOwner = mProfileOwners.get(userId); - return profileOwner != null && !profileOwner.userRestrictionsMigrated; + synchronized (mLock) { + OwnerInfo profileOwner = mProfileOwners.get(userId); + return profileOwner != null && !profileOwner.userRestrictionsMigrated; + } } /** Sets the user restrictions migrated flag, and also writes to the file. */ void setDeviceOwnerUserRestrictionsMigrated() { - if (mDeviceOwner != null) { - mDeviceOwner.userRestrictionsMigrated = true; + synchronized (mLock) { + if (mDeviceOwner != null) { + mDeviceOwner.userRestrictionsMigrated = true; + } + writeDeviceOwner(); } - writeDeviceOwner(); } /** Sets the remote bugreport uri and hash, and also writes to the file. */ void setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri, String remoteBugreportHash) { - if (mDeviceOwner != null) { - mDeviceOwner.remoteBugreportUri = remoteBugreportUri; - mDeviceOwner.remoteBugreportHash = remoteBugreportHash; + synchronized (mLock) { + if (mDeviceOwner != null) { + mDeviceOwner.remoteBugreportUri = remoteBugreportUri; + mDeviceOwner.remoteBugreportHash = remoteBugreportHash; + } + writeDeviceOwner(); } - writeDeviceOwner(); } /** Sets the user restrictions migrated flag, and also writes to the file. */ void setProfileOwnerUserRestrictionsMigrated(int userId) { - OwnerInfo profileOwner = mProfileOwners.get(userId); - if (profileOwner != null) { - profileOwner.userRestrictionsMigrated = true; + synchronized (mLock) { + OwnerInfo profileOwner = mProfileOwners.get(userId); + if (profileOwner != null) { + profileOwner.userRestrictionsMigrated = true; + } + writeProfileOwner(userId); } - writeProfileOwner(userId); } - private boolean readLegacyOwnerFile(File file) { + private boolean readLegacyOwnerFileLocked(File file) { if (!file.exists()) { // Already migrated or the device has no owners. return false; @@ -383,7 +451,7 @@ class Owners { } void writeDeviceOwner() { - synchronized (this) { + synchronized (mLock) { if (DEBUG) { Log.d(TAG, "Writing to device owner file"); } @@ -392,7 +460,7 @@ class Owners { } void writeProfileOwner(int userId) { - synchronized (this) { + synchronized (mLock) { if (DEBUG) { Log.d(TAG, "Writing to profile owner file for user " + userId); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 5c2e0baab768..ff7ca6201b55 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -700,6 +700,24 @@ public class CarrierConfigManager { public static final String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int"; + /** + * @hide + * The default value for preferred CDMA roaming mode (aka CDMA system select.) + * CDMA_ROAMING_MODE_RADIO_DEFAULT = the default roaming mode from the radio + * CDMA_ROAMING_MODE_HOME = Home Networks + * CDMA_ROAMING_MODE_AFFILIATED = Roaming on Affiliated networks + * CDMA_ROAMING_MODE_ANY = Roaming on any networks + */ + public static final String KEY_CDMA_ROAMING_MODE_INT = "cdma_roaming_mode_int"; + /** @hide */ + public static final int CDMA_ROAMING_MODE_RADIO_DEFAULT = -1; + /** @hide */ + public static final int CDMA_ROAMING_MODE_HOME = 0; + /** @hide */ + public static final int CDMA_ROAMING_MODE_AFFILIATED = 1; + /** @hide */ + public static final int CDMA_ROAMING_MODE_ANY = 2; + /** The default value for every variable. */ private final static PersistableBundle sDefaults; @@ -836,6 +854,7 @@ public class CarrierConfigManager { sDefaults.putString(KEY_MMS_USER_AGENT_STRING, ""); sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true); sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false); + sDefaults.putInt(KEY_CDMA_ROAMING_MODE_INT, CDMA_ROAMING_MODE_RADIO_DEFAULT); // Used for Sim card State detection app sDefaults.putStringArray(KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY, |