Merge "New intent action for returning account migration result"
diff --git a/api/current.txt b/api/current.txt
index 6e712c5..bd5596b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1711,6 +1711,7 @@
field public static final int paste = 16908322; // 0x1020022
field public static final int primary = 16908300; // 0x102000c
field public static final int progress = 16908301; // 0x102000d
+ field public static final int redo = 16908338; // 0x1020032
field public static final int secondaryProgress = 16908303; // 0x102000f
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
@@ -1727,6 +1728,7 @@
field public static final int text2 = 16908309; // 0x1020015
field public static final int title = 16908310; // 0x1020016
field public static final int toggle = 16908311; // 0x1020017
+ field public static final int undo = 16908337; // 0x1020031
field public static final int widget_frame = 16908312; // 0x1020018
}
@@ -2120,6 +2122,7 @@
field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974396; // 0x103023c
field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974397; // 0x103023d
field public static final int Theme_Material_Light_Dialog_Presentation = 16974398; // 0x103023e
+ field public static final int Theme_Material_Light_LightStatusBar = 16974563; // 0x10302e3
field public static final int Theme_Material_Light_NoActionBar = 16974401; // 0x1030241
field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974402; // 0x1030242
field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974403; // 0x1030243
@@ -28745,6 +28748,7 @@
method public boolean isInCall();
method public void showInCallScreen(boolean);
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
+ field public static final java.lang.String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
diff --git a/api/system-current.txt b/api/system-current.txt
index c6dacfe..36ac196 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1787,6 +1787,7 @@
field public static final int paste = 16908322; // 0x1020022
field public static final int primary = 16908300; // 0x102000c
field public static final int progress = 16908301; // 0x102000d
+ field public static final int redo = 16908338; // 0x1020032
field public static final int secondaryProgress = 16908303; // 0x102000f
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
@@ -1803,6 +1804,7 @@
field public static final int text2 = 16908309; // 0x1020015
field public static final int title = 16908310; // 0x1020016
field public static final int toggle = 16908311; // 0x1020017
+ field public static final int undo = 16908337; // 0x1020031
field public static final int widget_frame = 16908312; // 0x1020018
}
@@ -2199,6 +2201,7 @@
field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974396; // 0x103023c
field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974397; // 0x103023d
field public static final int Theme_Material_Light_Dialog_Presentation = 16974398; // 0x103023e
+ field public static final int Theme_Material_Light_LightStatusBar = 16974563; // 0x10302e3
field public static final int Theme_Material_Light_NoActionBar = 16974401; // 0x1030241
field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974402; // 0x1030242
field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974403; // 0x1030243
@@ -15118,6 +15121,8 @@
field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
field public static final int FLAG_BEACON = 8; // 0x8
+ field public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 64; // 0x40
+ field public static final int FLAG_BYPASS_MUTE = 128; // 0x80
field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
field public static final int FLAG_HW_HOTWORD = 32; // 0x20
field public static final int USAGE_ALARM = 4; // 0x4
@@ -30863,6 +30868,7 @@
field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
+ field public static final java.lang.String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java
index 26a61ae..5e88bca 100644
--- a/core/java/android/alsa/AlsaCardsParser.java
+++ b/core/java/android/alsa/AlsaCardsParser.java
@@ -117,6 +117,9 @@
cardRecord.parse(line, 0);
line = bufferedReader.readLine();
+ if (line == null) {
+ break;
+ }
if (DEBUG) {
Slog.i(TAG, " " + line);
}
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 6ef3da8..d5ae6c6 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -15,6 +15,7 @@
*/
package android.animation;
+import android.annotation.AnimatorRes;
import android.content.Context;
import android.content.res.ConfigurationBoundResourceCache;
import android.content.res.ConstantState;
@@ -82,7 +83,7 @@
* @return The animator object reference by the specified id
* @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
*/
- public static Animator loadAnimator(Context context, int id)
+ public static Animator loadAnimator(Context context, @AnimatorRes int id)
throws NotFoundException {
return loadAnimator(context.getResources(), context.getTheme(), id);
}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 014a7af..4cdd397 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -16,9 +16,12 @@
package android.app;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -256,7 +259,7 @@
*
* @see #setDisplayOptions(int, int)
*/
- public abstract void setCustomView(int resId);
+ public abstract void setCustomView(@LayoutRes int resId);
/**
* Set the icon to display in the 'home' section of the action bar.
@@ -271,7 +274,7 @@
* @see #setDisplayUseLogoEnabled(boolean)
* @see #setDisplayShowHomeEnabled(boolean)
*/
- public abstract void setIcon(int resId);
+ public abstract void setIcon(@DrawableRes int resId);
/**
* Set the icon to display in the 'home' section of the action bar.
@@ -301,7 +304,7 @@
* @see #setDisplayUseLogoEnabled(boolean)
* @see #setDisplayShowHomeEnabled(boolean)
*/
- public abstract void setLogo(int resId);
+ public abstract void setLogo(@DrawableRes int resId);
/**
* Set the logo to display in the 'home' section of the action bar.
@@ -397,7 +400,7 @@
* @see #setTitle(CharSequence)
* @see #setDisplayOptions(int, int)
*/
- public abstract void setTitle(int resId);
+ public abstract void setTitle(@StringRes int resId);
/**
* Set the action bar's subtitle. This will only be displayed if
@@ -420,7 +423,7 @@
* @see #setSubtitle(CharSequence)
* @see #setDisplayOptions(int, int)
*/
- public abstract void setSubtitle(int resId);
+ public abstract void setSubtitle(@StringRes int resId);
/**
* Set display options. This changes all display option bits at once. To change
@@ -892,7 +895,7 @@
* @see #setDisplayHomeAsUpEnabled(boolean)
* @see #setHomeActionContentDescription(int)
*/
- public void setHomeAsUpIndicator(int resId) { }
+ public void setHomeAsUpIndicator(@DrawableRes int resId) { }
/**
* Set an alternate description for the Home/Up action, when enabled.
@@ -931,7 +934,7 @@
* @see #setHomeAsUpIndicator(int)
* @see #setHomeAsUpIndicator(android.graphics.drawable.Drawable)
*/
- public void setHomeActionContentDescription(int resId) { }
+ public void setHomeActionContentDescription(@StringRes int resId) { }
/**
* Enable hiding the action bar on content scroll.
@@ -1154,7 +1157,7 @@
* @param resId Resource ID referring to the drawable to use as an icon
* @return The current instance for call chaining
*/
- public abstract Tab setIcon(int resId);
+ public abstract Tab setIcon(@DrawableRes int resId);
/**
* Set the text displayed on this tab. Text may be truncated if there is not
@@ -1172,7 +1175,7 @@
* @param resId A resource ID referring to the text that should be displayed
* @return The current instance for call chaining
*/
- public abstract Tab setText(int resId);
+ public abstract Tab setText(@StringRes int resId);
/**
* Set a custom view to be used for this tab. This overrides values set by
@@ -1190,7 +1193,7 @@
* @param layoutResId A layout resource to inflate and use as a custom tab view
* @return The current instance for call chaining
*/
- public abstract Tab setCustomView(int layoutResId);
+ public abstract Tab setCustomView(@LayoutRes int layoutResId);
/**
* Retrieve a previously set custom view for this tab.
@@ -1235,7 +1238,7 @@
* @see #setContentDescription(CharSequence)
* @see #getContentDescription()
*/
- public abstract Tab setContentDescription(int resId);
+ public abstract Tab setContentDescription(@StringRes int resId);
/**
* Set a description of this tab's content for use in accessibility support.
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aa1c70e..f0d98f8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,7 +16,13 @@
package android.app;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
+import android.annotation.IntDef;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleRes;
import android.os.PersistableBundle;
import android.transition.Scene;
import android.transition.TransitionManager;
@@ -2070,7 +2076,7 @@
* @return The view if found or null otherwise.
*/
@Nullable
- public View findViewById(int id) {
+ public View findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
@@ -2143,7 +2149,7 @@
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
- public void setContentView(int layoutResID) {
+ public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
@@ -3611,7 +3617,7 @@
* Convenience for calling
* {@link android.view.Window#setFeatureDrawableResource}.
*/
- public final void setFeatureDrawableResource(int featureId, int resId) {
+ public final void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
getWindow().setFeatureDrawableResource(featureId, resId);
}
@@ -3666,7 +3672,7 @@
}
@Override
- protected void onApplyThemeResource(Resources.Theme theme, int resid,
+ protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid,
boolean first) {
if (mParent == null) {
super.onApplyThemeResource(theme, resid, first);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index a8eb076..653b951 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1101,7 +1101,7 @@
@Override
public void dumpGfxInfo(FileDescriptor fd, String[] args) {
dumpGraphicsInfo(fd);
- WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
+ WindowManagerGlobal.getInstance().dumpGfxInfo(fd, args);
}
private void dumpDatabaseInfo(FileDescriptor fd, String[] args) {
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 3c6458f..c8f58c6 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -18,6 +18,10 @@
import com.android.internal.app.AlertController;
+import android.annotation.ArrayRes;
+import android.annotation.AttrRes;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
@@ -117,7 +121,7 @@
* or one of the constants {@link #THEME_TRADITIONAL},
* {@link #THEME_HOLO_DARK}, or {@link #THEME_HOLO_LIGHT}.
*/
- protected AlertDialog(Context context, int theme) {
+ protected AlertDialog(Context context, @AttrRes int theme) {
this(context, theme, true);
}
@@ -327,7 +331,7 @@
* @param resId the resourceId of the drawable to use as the icon or 0
* if you don't want an icon.
*/
- public void setIcon(int resId) {
+ public void setIcon(@DrawableRes int resId) {
mAlert.setIcon(resId);
}
@@ -340,7 +344,7 @@
*
* @param attrId ID of a theme attribute that points to a drawable resource.
*/
- public void setIconAttribute(int attrId) {
+ public void setIconAttribute(@AttrRes int attrId) {
TypedValue out = new TypedValue();
mContext.getTheme().resolveAttribute(attrId, out, true);
mAlert.setIcon(out.resourceId);
@@ -413,7 +417,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setTitle(int titleId) {
+ public Builder setTitle(@StringRes int titleId) {
P.mTitle = P.mContext.getText(titleId);
return this;
}
@@ -449,7 +453,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setMessage(int messageId) {
+ public Builder setMessage(@StringRes int messageId) {
P.mMessage = P.mContext.getText(messageId);
return this;
}
@@ -471,7 +475,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setIcon(int iconId) {
+ public Builder setIcon(@DrawableRes int iconId) {
P.mIconId = iconId;
return this;
}
@@ -495,7 +499,7 @@
*
* @param attrId ID of a theme attribute that points to a drawable resource.
*/
- public Builder setIconAttribute(int attrId) {
+ public Builder setIconAttribute(@AttrRes int attrId) {
TypedValue out = new TypedValue();
P.mContext.getTheme().resolveAttribute(attrId, out, true);
P.mIconId = out.resourceId;
@@ -509,7 +513,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setPositiveButton(int textId, final OnClickListener listener) {
+ public Builder setPositiveButton(@StringRes int textId, final OnClickListener listener) {
P.mPositiveButtonText = P.mContext.getText(textId);
P.mPositiveButtonListener = listener;
return this;
@@ -535,7 +539,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setNegativeButton(int textId, final OnClickListener listener) {
+ public Builder setNegativeButton(@StringRes int textId, final OnClickListener listener) {
P.mNegativeButtonText = P.mContext.getText(textId);
P.mNegativeButtonListener = listener;
return this;
@@ -561,7 +565,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setNeutralButton(int textId, final OnClickListener listener) {
+ public Builder setNeutralButton(@StringRes int textId, final OnClickListener listener) {
P.mNeutralButtonText = P.mContext.getText(textId);
P.mNeutralButtonListener = listener;
return this;
@@ -634,7 +638,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setItems(int itemsId, final OnClickListener listener) {
+ public Builder setItems(@ArrayRes int itemsId, final OnClickListener listener) {
P.mItems = P.mContext.getResources().getTextArray(itemsId);
P.mOnClickListener = listener;
return this;
@@ -706,7 +710,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setMultiChoiceItems(int itemsId, boolean[] checkedItems,
+ public Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems,
final OnMultiChoiceClickListener listener) {
P.mItems = P.mContext.getResources().getTextArray(itemsId);
P.mOnCheckboxClickListener = listener;
@@ -785,7 +789,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setSingleChoiceItems(int itemsId, int checkedItem,
+ public Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem,
final OnClickListener listener) {
P.mItems = P.mContext.getResources().getTextArray(itemsId);
P.mOnClickListener = listener;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index d808c8b..f35e746 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -16,6 +16,9 @@
package android.app;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
+import android.annotation.XmlRes;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Intent;
@@ -730,7 +733,7 @@
}
}
- @Override public Drawable getDrawable(String packageName, int resid,
+ @Override public Drawable getDrawable(String packageName, @DrawableRes int resid,
ApplicationInfo appInfo) {
ResourceName name = new ResourceName(packageName, resid);
Drawable dr = getCachedIcon(name);
@@ -1137,7 +1140,7 @@
}
@Override
- public CharSequence getText(String packageName, int resid,
+ public CharSequence getText(String packageName, @StringRes int resid,
ApplicationInfo appInfo) {
ResourceName name = new ResourceName(packageName, resid);
CharSequence text = getCachedString(name);
@@ -1170,7 +1173,7 @@
}
@Override
- public XmlResourceParser getXml(String packageName, int resid,
+ public XmlResourceParser getXml(String packageName, @XmlRes int resid,
ApplicationInfo appInfo) {
if (appInfo == null) {
try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 0098d86..db380ed 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2294,8 +2294,10 @@
if (container != null) {
compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();
}
- if (compatInfo == null && displayId == Display.DEFAULT_DISPLAY) {
- compatInfo = packageInfo.getCompatibilityInfo();
+ if (compatInfo == null) {
+ compatInfo = (displayId == Display.DEFAULT_DISPLAY)
+ ? packageInfo.getCompatibilityInfo()
+ : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
}
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
mDisplayAdjustments.setConfiguration(overrideConfiguration);
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index a3662b2..e465d57 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -16,6 +16,10 @@
package android.app;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
+import android.annotation.StringRes;
import com.android.internal.app.WindowDecorActionBar;
import android.annotation.Nullable;
@@ -478,7 +482,7 @@
* @return The view with the given id or null.
*/
@Nullable
- public View findViewById(int id) {
+ public View findViewById(@IdRes int id) {
return mWindow.findViewById(id);
}
@@ -488,7 +492,7 @@
*
* @param layoutResID Resource ID to be inflated.
*/
- public void setContentView(int layoutResID) {
+ public void setContentView(@LayoutRes int layoutResID) {
mWindow.setContentView(layoutResID);
}
@@ -542,7 +546,7 @@
*
* @param titleId the title's text resource identifier
*/
- public void setTitle(int titleId) {
+ public void setTitle(@StringRes int titleId) {
setTitle(mContext.getText(titleId));
}
@@ -1072,7 +1076,7 @@
* Convenience for calling
* {@link android.view.Window#setFeatureDrawableResource}.
*/
- public final void setFeatureDrawableResource(int featureId, int resId) {
+ public final void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
getWindow().setFeatureDrawableResource(featureId, resId);
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index f319309..c5f534c 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -18,6 +18,7 @@
import android.animation.Animator;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
@@ -795,7 +796,7 @@
*
* @param resId Resource id for the CharSequence text
*/
- public final CharSequence getText(int resId) {
+ public final CharSequence getText(@StringRes int resId) {
return getResources().getText(resId);
}
@@ -805,7 +806,7 @@
*
* @param resId Resource id for the string
*/
- public final String getString(int resId) {
+ public final String getString(@StringRes int resId) {
return getResources().getString(resId);
}
@@ -818,7 +819,7 @@
* @param formatArgs The format arguments that will be used for substitution.
*/
- public final String getString(int resId, Object... formatArgs) {
+ public final String getString(@StringRes int resId, Object... formatArgs) {
return getResources().getString(resId, formatArgs);
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index afdc917..975b20d 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -21,6 +21,7 @@
import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
import android.content.Context;
+import android.annotation.IdRes;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
@@ -396,7 +397,7 @@
*/
interface FragmentContainer {
@Nullable
- public View findViewById(int id);
+ public View findViewById(@IdRes int id);
public boolean hasView();
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 87e744c..9c00e1c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -165,6 +166,7 @@
* The resource id of a drawable to use as the icon in the status bar.
* This is required; notifications with an invalid icon resource will not be shown.
*/
+ @DrawableRes
public int icon;
/**
@@ -2128,7 +2130,7 @@
* A resource ID in the application's package of the drawable to use.
* @see Notification#icon
*/
- public Builder setSmallIcon(int icon) {
+ public Builder setSmallIcon(@DrawableRes int icon) {
mSmallIcon = icon;
return this;
}
@@ -2144,7 +2146,7 @@
* @see Notification#icon
* @see Notification#iconLevel
*/
- public Builder setSmallIcon(int icon, int level) {
+ public Builder setSmallIcon(@DrawableRes int icon, int level) {
mSmallIcon = icon;
mSmallIconLevel = level;
return this;
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index 922ebdd..c7d2140 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -19,6 +19,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.StringRes;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -682,6 +683,7 @@
* @return A resource id, or {@code 0} if no language model was specified.
* @see android.R.styleable#Searchable_voiceLanguageModel
*/
+ @StringRes
public int getVoiceLanguageModeId() {
return mVoiceLanguageModeId;
}
@@ -692,6 +694,7 @@
* @return A resource id, or {@code 0} if no voice prompt text was specified.
* @see android.R.styleable#Searchable_voicePromptText
*/
+ @StringRes
public int getVoicePromptTextId() {
return mVoicePromptTextId;
}
@@ -702,6 +705,7 @@
* @return A resource id, or {@code 0} if no language was specified.
* @see android.R.styleable#Searchable_voiceLanguage
*/
+ @StringRes
public int getVoiceLanguageId() {
return mVoiceLanguageId;
}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index c8e0031..21a3543 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.Nullable;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Intent;
@@ -498,6 +499,7 @@
* @return Return an IBinder through which clients can call on to the
* service.
*/
+ @Nullable
public abstract IBinder onBind(Intent intent);
/**
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 90d84ee..dcbd669 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.RawRes;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -707,7 +708,7 @@
* @throws IOException If an error occurs reverting to the built-in
* wallpaper.
*/
- public void setResource(int resid) throws IOException {
+ public void setResource(@RawRes int resid) throws IOException {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
return;
@@ -823,7 +824,7 @@
* with the given resource ID. That is, their wallpaper has been
* set through {@link #setResource(int)} with the same resource id.
*/
- public boolean hasResourceWallpaper(int resid) {
+ public boolean hasResourceWallpaper(@RawRes int resid) {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
return false;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index df620d0..eabe297 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -20,6 +20,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.annotation.StringRes;
+import android.annotation.StyleRes;
+import android.annotation.StyleableRes;
import android.annotation.SystemApi;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -365,7 +368,7 @@
*
* @param resId Resource id for the CharSequence text
*/
- public final CharSequence getText(int resId) {
+ public final CharSequence getText(@StringRes int resId) {
return getResources().getText(resId);
}
@@ -375,7 +378,7 @@
*
* @param resId Resource id for the string
*/
- public final String getString(int resId) {
+ public final String getString(@StringRes int resId) {
return getResources().getString(resId);
}
@@ -388,7 +391,7 @@
* @param formatArgs The format arguments that will be used for substitution.
*/
- public final String getString(int resId, Object... formatArgs) {
+ public final String getString(@StringRes int resId, Object... formatArgs) {
return getResources().getString(resId, formatArgs);
}
@@ -450,7 +453,7 @@
*
* @param resid The style resource describing the theme.
*/
- public abstract void setTheme(int resid);
+ public abstract void setTheme(@StyleRes int resid);
/** @hide Needed for some internal implementation... not public because
* you can't assume this actually means anything. */
@@ -484,7 +487,7 @@
* @see Resources.Theme#obtainStyledAttributes(int, int[])
*/
public final TypedArray obtainStyledAttributes(
- int resid, int[] attrs) throws Resources.NotFoundException {
+ @StyleableRes int resid, int[] attrs) throws Resources.NotFoundException {
return getTheme().obtainStyledAttributes(resid, attrs);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 582802b..3222b2b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -23,6 +23,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.AnyRes;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
@@ -762,11 +763,11 @@
* identifier.
*
* @param context The context of the application.
- * @param resourceId The resource idenfitier for the icon.
+ * @param resourceId The resource identifier for the icon.
* @return A new ShortcutIconResource with the specified's context package name
- * and icon resource idenfitier.
+ * and icon resource identifier.``
*/
- public static ShortcutIconResource fromContext(Context context, int resourceId) {
+ public static ShortcutIconResource fromContext(Context context, @AnyRes int resourceId) {
ShortcutIconResource icon = new ShortcutIconResource();
icon.packageName = context.getPackageName();
icon.resourceName = context.getResources().getResourceName(resourceId);
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index 5341ea8..6d79626 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.ArrayRes;
import android.os.Parcel;
import android.os.Parcelable;
@@ -277,7 +278,7 @@
* @param stringArrayResId the resource id for a string array containing the possible values.
* @see #setChoiceValues(String[])
*/
- public void setChoiceValues(Context context, int stringArrayResId) {
+ public void setChoiceValues(Context context, @ArrayRes int stringArrayResId) {
mChoiceValues = context.getResources().getStringArray(stringArrayResId);
}
@@ -307,7 +308,7 @@
* @param context the application context, used for retrieving the resources.
* @param stringArrayResId the resource id of a string array containing the possible entries.
*/
- public void setChoiceEntries(Context context, int stringArrayResId) {
+ public void setChoiceEntries(Context context, @ArrayRes int stringArrayResId) {
mChoiceEntries = context.getResources().getStringArray(stringArrayResId);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e9f7c50..ebc8e1e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -16,11 +16,14 @@
package android.content.pm;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.StringRes;
import android.annotation.SystemApi;
+import android.annotation.XmlRes;
import android.app.PackageDeleteObserver;
import android.app.PackageInstallObserver;
import android.app.admin.DevicePolicyManager;
@@ -2710,7 +2713,7 @@
* @return Returns a Drawable holding the requested image. Returns null if
* an image could not be found for any reason.
*/
- public abstract Drawable getDrawable(String packageName, int resid,
+ public abstract Drawable getDrawable(String packageName, @DrawableRes int resid,
ApplicationInfo appInfo);
/**
@@ -3012,7 +3015,7 @@
* @return Returns a CharSequence holding the requested text. Returns null
* if the text could not be found for any reason.
*/
- public abstract CharSequence getText(String packageName, int resid,
+ public abstract CharSequence getText(String packageName, @StringRes int resid,
ApplicationInfo appInfo);
/**
@@ -3031,7 +3034,7 @@
* data. Returns null if the xml resource could not be found for any
* reason.
*/
- public abstract XmlResourceParser getXml(String packageName, int resid,
+ public abstract XmlResourceParser getXml(String packageName, @XmlRes int resid,
ApplicationInfo appInfo);
/**
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 6fb7299..3e922f2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -23,8 +23,22 @@
import android.animation.Animator;
import android.animation.StateListAnimator;
+import android.annotation.AnimRes;
+import android.annotation.AnyRes;
+import android.annotation.ArrayRes;
+import android.annotation.BoolRes;
+import android.annotation.ColorRes;
+import android.annotation.DimenRes;
+import android.annotation.DrawableRes;
+import android.annotation.FractionRes;
+import android.annotation.IntegerRes;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.PluralsRes;
+import android.annotation.RawRes;
+import android.annotation.StringRes;
+import android.annotation.XmlRes;
import android.content.pm.ActivityInfo;
import android.content.res.ColorStateList.ColorStateListFactory;
import android.graphics.Movie;
@@ -287,7 +301,7 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
- public CharSequence getText(int id) throws NotFoundException {
+ public CharSequence getText(@StringRes int id) throws NotFoundException {
CharSequence res = mAssets.getResourceText(id);
if (res != null) {
return res;
@@ -316,7 +330,8 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
- public CharSequence getQuantityText(int id, int quantity) throws NotFoundException {
+ public CharSequence getQuantityText(@PluralsRes int id, int quantity)
+ throws NotFoundException {
NativePluralRules rule = getPluralRule();
CharSequence res = mAssets.getResourceBagText(id,
attrForQuantityCode(rule.quantityForInt(quantity)));
@@ -377,7 +392,7 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getString(int id) throws NotFoundException {
+ public String getString(@StringRes int id) throws NotFoundException {
CharSequence res = getText(id);
if (res != null) {
return res.toString();
@@ -405,7 +420,8 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getString(int id, Object... formatArgs) throws NotFoundException {
+ public String getString(@StringRes int id, Object... formatArgs)
+ throws NotFoundException {
String raw = getString(id);
return String.format(mConfiguration.locale, raw, formatArgs);
}
@@ -435,7 +451,7 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getQuantityString(int id, int quantity, Object... formatArgs)
+ public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
throws NotFoundException {
String raw = getQuantityText(id, quantity).toString();
return String.format(mConfiguration.locale, raw, formatArgs);
@@ -461,7 +477,8 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getQuantityString(int id, int quantity) throws NotFoundException {
+ public String getQuantityString(@PluralsRes int id, int quantity)
+ throws NotFoundException {
return getQuantityText(id, quantity).toString();
}
@@ -479,7 +496,7 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information, or def if id is 0 or not found.
*/
- public CharSequence getText(int id, CharSequence def) {
+ public CharSequence getText(@StringRes int id, CharSequence def) {
CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
return res != null ? res : def;
}
@@ -495,7 +512,7 @@
*
* @return The styled text array associated with the resource.
*/
- public CharSequence[] getTextArray(int id) throws NotFoundException {
+ public CharSequence[] getTextArray(@ArrayRes int id) throws NotFoundException {
CharSequence[] res = mAssets.getResourceTextArray(id);
if (res != null) {
return res;
@@ -515,7 +532,8 @@
*
* @return The string array associated with the resource.
*/
- public String[] getStringArray(int id) throws NotFoundException {
+ public String[] getStringArray(@ArrayRes int id)
+ throws NotFoundException {
String[] res = mAssets.getResourceStringArray(id);
if (res != null) {
return res;
@@ -535,7 +553,7 @@
*
* @return The int array associated with the resource.
*/
- public int[] getIntArray(int id) throws NotFoundException {
+ public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
int[] res = mAssets.getArrayIntResource(id);
if (res != null) {
return res;
@@ -557,7 +575,8 @@
* Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
* when done with it.
*/
- public TypedArray obtainTypedArray(int id) throws NotFoundException {
+ public TypedArray obtainTypedArray(@ArrayRes int id)
+ throws NotFoundException {
int len = mAssets.getArraySize(id);
if (len < 0) {
throw new NotFoundException("Array resource ID #0x"
@@ -588,7 +607,7 @@
* @see #getDimensionPixelOffset
* @see #getDimensionPixelSize
*/
- public float getDimension(int id) throws NotFoundException {
+ public float getDimension(@DimenRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -623,7 +642,7 @@
* @see #getDimension
* @see #getDimensionPixelSize
*/
- public int getDimensionPixelOffset(int id) throws NotFoundException {
+ public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -660,7 +679,7 @@
* @see #getDimension
* @see #getDimensionPixelOffset
*/
- public int getDimensionPixelSize(int id) throws NotFoundException {
+ public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -694,7 +713,7 @@
*
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*/
- public float getFraction(int id, int base, int pbase) {
+ public float getFraction(@FractionRes int id, int base, int pbase) {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -744,7 +763,7 @@
*/
@Deprecated
@Nullable
- public Drawable getDrawable(int id) throws NotFoundException {
+ public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
final Drawable d = getDrawable(id, null);
if (d != null && d.canApplyTheme()) {
Log.w(TAG, "Drawable " + getResourceName(id) + " has unresolved theme "
@@ -769,7 +788,7 @@
* not exist.
*/
@Nullable
- public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
+ public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -817,7 +836,7 @@
*/
@Deprecated
@Nullable
- public Drawable getDrawableForDensity(int id, int density) throws NotFoundException {
+ public Drawable getDrawableForDensity(@DrawableRes int id, int density) throws NotFoundException {
return getDrawableForDensity(id, density, null);
}
@@ -836,7 +855,7 @@
* not exist.
*/
@Nullable
- public Drawable getDrawableForDensity(int id, int density, @Nullable Theme theme) {
+ public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -880,7 +899,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public Movie getMovie(int id) throws NotFoundException {
+ public Movie getMovie(@RawRes int id) throws NotFoundException {
InputStream is = openRawResource(id);
Movie movie = Movie.decodeStream(is);
try {
@@ -907,7 +926,7 @@
* @return A single color value in the form 0xAARRGGBB.
* @deprecated Use {@link #getColor(int, Theme)} instead.
*/
- public int getColor(int id) throws NotFoundException {
+ public int getColor(@ColorRes int id) throws NotFoundException {
return getColor(id, null);
}
@@ -927,7 +946,7 @@
*
* @return A single color value in the form 0xAARRGGBB.
*/
- public int getColor(int id, @Nullable Theme theme) throws NotFoundException {
+ public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -975,7 +994,7 @@
* @deprecated Use {@link #getColorStateList(int, Theme)} instead.
*/
@Nullable
- public ColorStateList getColorStateList(int id) throws NotFoundException {
+ public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
final ColorStateList csl = getColorStateList(id, null);
if (csl != null && csl.canApplyTheme()) {
Log.w(TAG, "ColorStateList " + getResourceName(id) + " has "
@@ -1005,7 +1024,7 @@
* color or multiple colors that can be selected based on a state.
*/
@Nullable
- public ColorStateList getColorStateList(int id, @Nullable Theme theme)
+ public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
@@ -1043,7 +1062,7 @@
*
* @return Returns the boolean value contained in the resource.
*/
- public boolean getBoolean(int id) throws NotFoundException {
+ public boolean getBoolean(@BoolRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -1071,7 +1090,7 @@
*
* @return Returns the integer value contained in the resource.
*/
- public int getInteger(int id) throws NotFoundException {
+ public int getInteger(@IntegerRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -1136,7 +1155,7 @@
*
* @see #getXml
*/
- public XmlResourceParser getLayout(int id) throws NotFoundException {
+ public XmlResourceParser getLayout(@LayoutRes int id) throws NotFoundException {
return loadXmlResourceParser(id, "layout");
}
@@ -1160,7 +1179,7 @@
*
* @see #getXml
*/
- public XmlResourceParser getAnimation(int id) throws NotFoundException {
+ public XmlResourceParser getAnimation(@AnimRes int id) throws NotFoundException {
return loadXmlResourceParser(id, "anim");
}
@@ -1185,7 +1204,7 @@
*
* @see android.util.AttributeSet
*/
- public XmlResourceParser getXml(int id) throws NotFoundException {
+ public XmlResourceParser getXml(@XmlRes int id) throws NotFoundException {
return loadXmlResourceParser(id, "xml");
}
@@ -1203,7 +1222,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public InputStream openRawResource(int id) throws NotFoundException {
+ public InputStream openRawResource(@RawRes int id) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -1235,7 +1254,8 @@
*
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*/
- public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
+ public InputStream openRawResource(@RawRes int id, TypedValue value)
+ throws NotFoundException {
getValue(id, value, true);
try {
@@ -1270,7 +1290,8 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
+ public AssetFileDescriptor openRawResourceFd(@RawRes int id)
+ throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -1315,7 +1336,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public void getValue(int id, TypedValue outValue, boolean resolveRefs)
+ public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
if (found) {
@@ -1338,8 +1359,8 @@
* not exist.
* @see #getValue(String, TypedValue, boolean)
*/
- public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs)
- throws NotFoundException {
+ public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
+ boolean resolveRefs) throws NotFoundException {
boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
if (found) {
return;
@@ -1698,7 +1719,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID
* does not exist.
*/
- public Drawable getDrawable(int id) throws NotFoundException {
+ public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
return Resources.this.getDrawable(id, this);
}
@@ -2103,7 +2124,7 @@
*
* @hide
*/
- public static boolean resourceHasPackage(int resid) {
+ public static boolean resourceHasPackage(@AnyRes int resid) {
return (resid >>> 24) != 0;
}
@@ -2121,7 +2142,7 @@
* @see #getResourceTypeName
* @see #getResourceEntryName
*/
- public String getResourceName(int resid) throws NotFoundException {
+ public String getResourceName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourceName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
@@ -2140,7 +2161,7 @@
*
* @see #getResourceName
*/
- public String getResourcePackageName(int resid) throws NotFoundException {
+ public String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourcePackageName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
@@ -2159,7 +2180,7 @@
*
* @see #getResourceName
*/
- public String getResourceTypeName(int resid) throws NotFoundException {
+ public String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourceTypeName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
@@ -2178,7 +2199,7 @@
*
* @see #getResourceName
*/
- public String getResourceEntryName(int resid) throws NotFoundException {
+ public String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourceEntryName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index f15b6b9..3d43304 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -16,6 +16,7 @@
package android.content.res;
+import android.annotation.AnyRes;
import android.annotation.Nullable;
import android.graphics.drawable.Drawable;
import android.os.StrictMode;
@@ -786,6 +787,7 @@
* @return Attribute resource identifier, or defValue if not defined.
* @throws RuntimeException if the TypedArray has already been recycled.
*/
+ @AnyRes
public int getResourceId(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
diff --git a/core/java/android/gesture/GestureLibraries.java b/core/java/android/gesture/GestureLibraries.java
index 6d6c156..611d9ab 100644
--- a/core/java/android/gesture/GestureLibraries.java
+++ b/core/java/android/gesture/GestureLibraries.java
@@ -16,6 +16,7 @@
package android.gesture;
+import android.annotation.RawRes;
import android.util.Log;
import static android.gesture.GestureConstants.*;
import android.content.Context;
@@ -44,7 +45,7 @@
return fromFile(context.getFileStreamPath(name));
}
- public static GestureLibrary fromRawResource(Context context, int resourceId) {
+ public static GestureLibrary fromRawResource(Context context, @RawRes int resourceId) {
return new ResourceGestureLibrary(context, resourceId);
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index f218b65..481fc2f 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -19,6 +19,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import android.annotation.DrawableRes;
import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context;
@@ -1178,7 +1179,7 @@
return isExtractViewShown() ? View.GONE : View.INVISIBLE;
}
- public void showStatusIcon(int iconResId) {
+ public void showStatusIcon(@DrawableRes int iconResId) {
mStatusIcon = iconResId;
mImm.showStatusIcon(mToken, getPackageName(), iconResId);
}
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 4fe54c0..45f1889 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -18,6 +18,7 @@
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -519,7 +520,8 @@
* @param width sets width of keyboard
* @param height sets height of keyboard
*/
- public Keyboard(Context context, int xmlLayoutResId, int modeId, int width, int height) {
+ public Keyboard(Context context, @XmlRes int xmlLayoutResId, int modeId, int width,
+ int height) {
mDisplayWidth = width;
mDisplayHeight = height;
@@ -540,7 +542,7 @@
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
* @param modeId keyboard mode identifier
*/
- public Keyboard(Context context, int xmlLayoutResId, int modeId) {
+ public Keyboard(Context context, @XmlRes int xmlLayoutResId, int modeId) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
mDisplayWidth = dm.widthPixels;
mDisplayHeight = dm.heightPixels;
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 7785f2b..47e8e69 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -301,7 +301,7 @@
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
- throw new RuntimeException("An error occured while executing doInBackground()",
+ throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cd45cfb..4dadda2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -592,6 +592,86 @@
}
}
+ /**
+ * Optional detailed information that can go into a history step. This is typically
+ * generated each time the battery level changes.
+ */
+ public final static class HistoryStepDetails {
+ // Time (in 1/100 second) spent in user space and the kernel since the last step.
+ public int userTime;
+ public int systemTime;
+
+ // Top three apps using CPU in the last step, with times in 1/100 second.
+ public int appCpuUid1;
+ public int appCpuUTime1;
+ public int appCpuSTime1;
+ public int appCpuUid2;
+ public int appCpuUTime2;
+ public int appCpuSTime2;
+ public int appCpuUid3;
+ public int appCpuUTime3;
+ public int appCpuSTime3;
+
+ // Information from /proc/stat
+ public int statUserTime;
+ public int statSystemTime;
+ public int statIOWaitTime;
+ public int statIrqTime;
+ public int statSoftIrqTime;
+ public int statIdlTime;
+
+ public HistoryStepDetails() {
+ clear();
+ }
+
+ public void clear() {
+ userTime = systemTime = 0;
+ appCpuUid1 = appCpuUid2 = appCpuUid3 = -1;
+ appCpuUTime1 = appCpuSTime1 = appCpuUTime2 = appCpuSTime2
+ = appCpuUTime3 = appCpuSTime3 = 0;
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeInt(userTime);
+ out.writeInt(systemTime);
+ out.writeInt(appCpuUid1);
+ out.writeInt(appCpuUTime1);
+ out.writeInt(appCpuSTime1);
+ out.writeInt(appCpuUid2);
+ out.writeInt(appCpuUTime2);
+ out.writeInt(appCpuSTime2);
+ out.writeInt(appCpuUid3);
+ out.writeInt(appCpuUTime3);
+ out.writeInt(appCpuSTime3);
+ out.writeInt(statUserTime);
+ out.writeInt(statSystemTime);
+ out.writeInt(statIOWaitTime);
+ out.writeInt(statIrqTime);
+ out.writeInt(statSoftIrqTime);
+ out.writeInt(statIdlTime);
+ }
+
+ public void readFromParcel(Parcel in) {
+ userTime = in.readInt();
+ systemTime = in.readInt();
+ appCpuUid1 = in.readInt();
+ appCpuUTime1 = in.readInt();
+ appCpuSTime1 = in.readInt();
+ appCpuUid2 = in.readInt();
+ appCpuUTime2 = in.readInt();
+ appCpuSTime2 = in.readInt();
+ appCpuUid3 = in.readInt();
+ appCpuUTime3 = in.readInt();
+ appCpuSTime3 = in.readInt();
+ statUserTime = in.readInt();
+ statSystemTime = in.readInt();
+ statIOWaitTime = in.readInt();
+ statIrqTime = in.readInt();
+ statSoftIrqTime = in.readInt();
+ statIdlTime = in.readInt();
+ }
+ }
+
public final static class HistoryItem implements Parcelable {
public HistoryItem next;
@@ -687,6 +767,9 @@
// Kernel wakeup reason at this point.
public HistoryTag wakeReasonTag;
+ // Non-null when there is more detailed information at this step.
+ public HistoryStepDetails stepDetails;
+
public static final int EVENT_FLAG_START = 0x8000;
public static final int EVENT_FLAG_FINISH = 0x4000;
@@ -3692,10 +3775,115 @@
}
}
pw.println();
+ if (rec.stepDetails != null) {
+ if (!checkin) {
+ pw.print(" Details: cpu=");
+ pw.print(rec.stepDetails.userTime);
+ pw.print("u+");
+ pw.print(rec.stepDetails.systemTime);
+ pw.print("s");
+ if (rec.stepDetails.appCpuUid1 >= 0) {
+ pw.print(" (");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
+ rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
+ if (rec.stepDetails.appCpuUid2 >= 0) {
+ pw.print(", ");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
+ rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
+ }
+ if (rec.stepDetails.appCpuUid3 >= 0) {
+ pw.print(", ");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
+ rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
+ }
+ pw.print(')');
+ }
+ pw.println();
+ pw.print(" /proc/stat=");
+ pw.print(rec.stepDetails.statUserTime);
+ pw.print(" usr, ");
+ pw.print(rec.stepDetails.statSystemTime);
+ pw.print(" sys, ");
+ pw.print(rec.stepDetails.statIOWaitTime);
+ pw.print(" io, ");
+ pw.print(rec.stepDetails.statIrqTime);
+ pw.print(" irq, ");
+ pw.print(rec.stepDetails.statSoftIrqTime);
+ pw.print(" sirq, ");
+ pw.print(rec.stepDetails.statIdlTime);
+ pw.print(" idle");
+ int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
+ + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
+ + rec.stepDetails.statSoftIrqTime;
+ int total = totalRun + rec.stepDetails.statIdlTime;
+ if (total > 0) {
+ pw.print(" (");
+ float perc = ((float)totalRun) / ((float)total) * 100;
+ pw.print(String.format("%.1f%%", perc));
+ pw.print(" of ");
+ StringBuilder sb = new StringBuilder(64);
+ formatTimeMsNoSpace(sb, total*10);
+ pw.print(sb);
+ pw.print(")");
+ }
+ pw.println();
+ } else {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
+ pw.print(rec.stepDetails.userTime);
+ pw.print(":");
+ pw.print(rec.stepDetails.systemTime);
+ if (rec.stepDetails.appCpuUid1 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
+ rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
+ if (rec.stepDetails.appCpuUid2 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
+ rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
+ }
+ if (rec.stepDetails.appCpuUid3 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
+ rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
+ }
+ }
+ pw.println();
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
+ pw.print(rec.stepDetails.statUserTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statSystemTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIOWaitTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIrqTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statSoftIrqTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIdlTime);
+ pw.println();
+ }
+ }
oldState = rec.states;
oldState2 = rec.states2;
}
}
+
+ private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
+ UserHandle.formatUid(pw, uid);
+ pw.print("=");
+ pw.print(utime);
+ pw.print("u+");
+ pw.print(stime);
+ pw.print("s");
+ }
+
+ private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
+ pw.print('/');
+ pw.print(uid);
+ pw.print(":");
+ pw.print(utime);
+ pw.print(":");
+ pw.print(stime);
+ }
}
private void printSizeValue(PrintWriter pw, long size) {
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index b5295fb..236003b 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -21,6 +21,7 @@
import android.content.pm.UserInfo;
import android.content.RestrictionEntry;
import android.graphics.Bitmap;
+import android.os.ParcelFileDescriptor;
/**
* {@hide}
@@ -32,7 +33,7 @@
boolean removeUser(int userHandle);
void setUserName(int userHandle, String name);
void setUserIcon(int userHandle, in Bitmap icon);
- Bitmap getUserIcon(int userHandle);
+ ParcelFileDescriptor getUserIcon(int userHandle);
List<UserInfo> getUsers(boolean excludeDying);
List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
UserInfo getProfileParent(int userHandle);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d124a49..650f3b3 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -22,6 +22,7 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.provider.Settings;
@@ -30,6 +31,7 @@
import com.android.internal.R;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -114,6 +116,7 @@
/**
* Specifies if a user is disallowed from configuring bluetooth.
+ * This does <em>not</em> restrict the user from turning bluetooth on or off.
* The default value is <code>false</code>.
* <p/>This restriction has no effect in a managed profile.
*
@@ -1083,11 +1086,21 @@
*/
public Bitmap getUserIcon(int userHandle) {
try {
- return mService.getUserIcon(userHandle);
+ ParcelFileDescriptor fd = mService.getUserIcon(userHandle);
+ if (fd != null) {
+ try {
+ return BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
+ } finally {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ }
+ }
+ }
} catch (RemoteException re) {
Log.w(TAG, "Could not get the user icon ", re);
- return null;
}
+ return null;
}
/**
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index b65eac7..1b226c1 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -17,6 +17,8 @@
package android.preference;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@@ -168,7 +170,7 @@
*
* @param dialogIconRes The icon, as a resource ID.
*/
- public void setDialogIcon(int dialogIconRes) {
+ public void setDialogIcon(@DrawableRes int dialogIconRes) {
mDialogIcon = getContext().getDrawable(dialogIconRes);
}
@@ -194,7 +196,7 @@
* @see #setPositiveButtonText(CharSequence)
* @param positiveButtonTextResId The positive button text as a resource.
*/
- public void setPositiveButtonText(int positiveButtonTextResId) {
+ public void setPositiveButtonText(@StringRes int positiveButtonTextResId) {
setPositiveButtonText(getContext().getString(positiveButtonTextResId));
}
@@ -222,7 +224,7 @@
* @see #setNegativeButtonText(CharSequence)
* @param negativeButtonTextResId The negative button text as a resource.
*/
- public void setNegativeButtonText(int negativeButtonTextResId) {
+ public void setNegativeButtonText(@StringRes int negativeButtonTextResId) {
setNegativeButtonText(getContext().getString(negativeButtonTextResId));
}
diff --git a/core/java/android/preference/GenericInflater.java b/core/java/android/preference/GenericInflater.java
index 7de7d1c..c84dbf1 100644
--- a/core/java/android/preference/GenericInflater.java
+++ b/core/java/android/preference/GenericInflater.java
@@ -23,6 +23,8 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.AnyRes;
+import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
@@ -216,7 +218,7 @@
* this is the root item; otherwise it is the root of the inflated
* XML file.
*/
- public T inflate(int resource, P root) {
+ public T inflate(@XmlRes int resource, P root) {
return inflate(resource, root, root != null);
}
@@ -256,7 +258,7 @@
* attachToRoot is true, this is root; otherwise it is the root of
* the inflated XML file.
*/
- public T inflate(int resource, P root, boolean attachToRoot) {
+ public T inflate(@XmlRes int resource, P root, boolean attachToRoot) {
if (DEBUG) System.out.println("INFLATING from resource: " + resource);
XmlResourceParser parser = getContext().getResources().getXml(resource);
try {
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
index 9482a72..2700373 100644
--- a/core/java/android/preference/ListPreference.java
+++ b/core/java/android/preference/ListPreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.ArrayRes;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
@@ -91,7 +92,7 @@
* @see #setEntries(CharSequence[])
* @param entriesResId The entries array as a resource.
*/
- public void setEntries(int entriesResId) {
+ public void setEntries(@ArrayRes int entriesResId) {
setEntries(getContext().getResources().getTextArray(entriesResId));
}
@@ -119,7 +120,7 @@
* @see #setEntryValues(CharSequence[])
* @param entryValuesResId The entry values array as a resource.
*/
- public void setEntryValues(int entryValuesResId) {
+ public void setEntryValues(@ArrayRes int entryValuesResId) {
setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
}
diff --git a/core/java/android/preference/MultiCheckPreference.java b/core/java/android/preference/MultiCheckPreference.java
index 57c906d..c1260a4 100644
--- a/core/java/android/preference/MultiCheckPreference.java
+++ b/core/java/android/preference/MultiCheckPreference.java
@@ -18,6 +18,7 @@
import java.util.Arrays;
+import android.annotation.ArrayRes;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
@@ -96,7 +97,7 @@
* @see #setEntries(CharSequence[])
* @param entriesResId The entries array as a resource.
*/
- public void setEntries(int entriesResId) {
+ public void setEntries(@ArrayRes int entriesResId) {
setEntries(getContext().getResources().getTextArray(entriesResId));
}
@@ -126,7 +127,7 @@
* @see #setEntryValues(CharSequence[])
* @param entryValuesResId The entry values array as a resource.
*/
- public void setEntryValues(int entryValuesResId) {
+ public void setEntryValues(@ArrayRes int entryValuesResId) {
setEntryValuesCS(getContext().getResources().getTextArray(entryValuesResId));
}
diff --git a/core/java/android/preference/MultiSelectListPreference.java b/core/java/android/preference/MultiSelectListPreference.java
index 6c4c20f..138bd878 100644
--- a/core/java/android/preference/MultiSelectListPreference.java
+++ b/core/java/android/preference/MultiSelectListPreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.ArrayRes;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
@@ -87,7 +88,7 @@
* @see #setEntries(CharSequence[])
* @param entriesResId The entries array as a resource.
*/
- public void setEntries(int entriesResId) {
+ public void setEntries(@ArrayRes int entriesResId) {
setEntries(getContext().getResources().getTextArray(entriesResId));
}
@@ -115,7 +116,7 @@
* @see #setEntryValues(CharSequence[])
* @param entryValuesResId The entry values array as a resource.
*/
- public void setEntryValues(int entryValuesResId) {
+ public void setEntryValues(@ArrayRes int entryValuesResId) {
setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
}
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 0224c73..78928b2 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -18,6 +18,9 @@
import com.android.internal.util.CharSequences;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -424,7 +427,7 @@
* a {@link View}.
* @see #setWidgetLayoutResource(int)
*/
- public void setLayoutResource(int layoutResId) {
+ public void setLayoutResource(@LayoutRes int layoutResId) {
if (layoutResId != mLayoutResId) {
// Layout changed
mCanRecycleLayout = false;
@@ -438,6 +441,7 @@
*
* @return The layout resource ID.
*/
+ @LayoutRes
public int getLayoutResource() {
return mLayoutResId;
}
@@ -452,7 +456,7 @@
* main layout.
* @see #setLayoutResource(int)
*/
- public void setWidgetLayoutResource(int widgetLayoutResId) {
+ public void setWidgetLayoutResource(@LayoutRes int widgetLayoutResId) {
if (widgetLayoutResId != mWidgetLayoutResId) {
// Layout changed
mCanRecycleLayout = false;
@@ -465,6 +469,7 @@
*
* @return The layout resource ID.
*/
+ @LayoutRes
public int getWidgetLayoutResource() {
return mWidgetLayoutResId;
}
@@ -648,7 +653,7 @@
* @see #setTitle(CharSequence)
* @param titleResId The title as a resource ID.
*/
- public void setTitle(int titleResId) {
+ public void setTitle(@StringRes int titleResId) {
setTitle(mContext.getString(titleResId));
mTitleRes = titleResId;
}
@@ -660,6 +665,7 @@
* @return The title resource.
* @see #setTitle(int)
*/
+ @StringRes
public int getTitleRes() {
return mTitleRes;
}
@@ -696,7 +702,7 @@
* @see #setIcon(Drawable)
* @param iconResId The icon as a resource ID.
*/
- public void setIcon(int iconResId) {
+ public void setIcon(@DrawableRes int iconResId) {
mIconResId = iconResId;
setIcon(mContext.getDrawable(iconResId));
}
@@ -739,7 +745,7 @@
* @see #setSummary(CharSequence)
* @param summaryResId The summary as a resource.
*/
- public void setSummary(int summaryResId) {
+ public void setSummary(@StringRes int summaryResId) {
setSummary(mContext.getString(summaryResId));
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 04cd7d5..0d80c0d 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -16,6 +16,8 @@
package android.preference;
+import android.annotation.StringRes;
+import android.annotation.XmlRes;
import android.app.Fragment;
import android.app.FragmentBreadCrumbs;
import android.app.FragmentManager;
@@ -337,6 +339,7 @@
* Resource ID of title of the header that is shown to the user.
* @attr ref android.R.styleable#PreferenceHeader_title
*/
+ @StringRes
public int titleRes;
/**
@@ -349,6 +352,7 @@
* Resource ID of optional summary describing what this header controls.
* @attr ref android.R.styleable#PreferenceHeader_summary
*/
+ @StringRes
public int summaryRes;
/**
@@ -361,6 +365,7 @@
* Resource ID of optional text to show as the title in the bread crumb.
* @attr ref android.R.styleable#PreferenceHeader_breadCrumbTitle
*/
+ @StringRes
public int breadCrumbTitleRes;
/**
@@ -373,6 +378,7 @@
* Resource ID of optional text to show as the short title in the bread crumb.
* @attr ref android.R.styleable#PreferenceHeader_breadCrumbShortTitle
*/
+ @StringRes
public int breadCrumbShortTitleRes;
/**
@@ -797,7 +803,7 @@
* @param resid The XML resource to load and parse.
* @param target The list in which the parsed headers should be placed.
*/
- public void loadHeadersFromResource(int resid, List<Header> target) {
+ public void loadHeadersFromResource(@XmlRes int resid, List<Header> target) {
XmlResourceParser parser = null;
try {
parser = getResources().getXml(resid);
@@ -1086,7 +1092,7 @@
* fragment.
*/
public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
- int titleRes, int shortTitleRes) {
+ @StringRes int titleRes, int shortTitleRes) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, getClass());
intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
@@ -1124,7 +1130,8 @@
* this set of preferences.
*/
public void startWithFragment(String fragmentName, Bundle args,
- Fragment resultTo, int resultRequestCode, int titleRes, int shortTitleRes) {
+ Fragment resultTo, int resultRequestCode, @StringRes int titleRes,
+ @StringRes int shortTitleRes) {
Intent intent = onBuildStartFragmentIntent(fragmentName, args, titleRes, shortTitleRes);
if (resultTo == null) {
startActivity(intent);
@@ -1343,9 +1350,9 @@
* preference panel is done. The launched panel must use
* {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
* @param resultRequestCode If resultTo is non-null, this is the caller's
- * request code to be received with the resut.
+ * request code to be received with the result.
*/
- public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
+ public void startPreferencePanel(String fragmentClass, Bundle args, @StringRes int titleRes,
CharSequence titleText, Fragment resultTo, int resultRequestCode) {
if (mSinglePane) {
startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0);
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index 0a0e625..55ee77a 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.XmlRes;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
@@ -263,7 +264,7 @@
* root).
* @hide
*/
- public PreferenceScreen inflateFromResource(Context context, int resId,
+ public PreferenceScreen inflateFromResource(Context context, @XmlRes int resId,
PreferenceScreen rootPreferences) {
// Block commits
setNoCommit(true);
@@ -438,7 +439,7 @@
* and clear it followed by a call to this method with this
* parameter set to true.
*/
- public static void setDefaultValues(Context context, int resId, boolean readAgain) {
+ public static void setDefaultValues(Context context, @XmlRes int resId, boolean readAgain) {
// Use the default shared preferences name and mode
setDefaultValues(context, getDefaultSharedPreferencesName(context),
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index c3dd4ce..30da0e7 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
+import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
@@ -174,6 +175,11 @@
}
if (mRingtone != null) {
try {
+ mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
+ .getAudioAttributes())
+ .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
+ AudioAttributes.FLAG_BYPASS_MUTE)
+ .build());
mRingtone.play();
} catch (Throwable e) {
Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e);
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index 53b5aad..9c3cefc 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -169,7 +170,7 @@
*
* @param resId The text as a string resource ID
*/
- public void setSwitchTextOn(int resId) {
+ public void setSwitchTextOn(@StringRes int resId) {
setSwitchTextOn(getContext().getString(resId));
}
@@ -179,7 +180,7 @@
*
* @param resId The text as a string resource ID
*/
- public void setSwitchTextOff(int resId) {
+ public void setSwitchTextOff(@StringRes int resId) {
setSwitchTextOff(getContext().getString(resId));
}
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index 3823b27..7037aca 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
@@ -116,7 +117,7 @@
* @see #setSummaryOn(CharSequence)
* @param summaryResId The summary as a resource.
*/
- public void setSummaryOn(int summaryResId) {
+ public void setSummaryOn(@StringRes int summaryResId) {
setSummaryOn(getContext().getString(summaryResId));
}
@@ -144,7 +145,7 @@
* @see #setSummaryOff(CharSequence)
* @param summaryResId The summary as a resource.
*/
- public void setSummaryOff(int summaryResId) {
+ public void setSummaryOff(@StringRes int summaryResId) {
setSummaryOff(getContext().getString(summaryResId));
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index f023df7..266922d 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -33,7 +33,9 @@
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.DataUsageFeedback;
+import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
@@ -336,22 +338,33 @@
// that was encoded into call log databases.
/**
- * The component name of the account in string form.
+ * The component name of the account used to place or receive the call; in string form.
* <P>Type: TEXT</P>
*/
public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
/**
- * The identifier of a account that is unique to a specified component.
+ * The identifier for the account used to place or receive the call.
* <P>Type: TEXT</P>
*/
public static final String PHONE_ACCOUNT_ID = "subscription_id";
/**
- * The identifier of a account that is unique to a specified component. Equivalent value
- * to {@link #PHONE_ACCOUNT_ID}. For ContactsProvider internal use only.
+ * The address associated with the account used to place or receive the call; in string
+ * form. For SIM-based calls, this is the user's own phone number.
+ * <P>Type: TEXT</P>
+ *
+ * @hide
+ */
+ public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address";
+
+ /**
+ * The subscription ID used to place this call. This is no longer used and has been
+ * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID.
+ * For ContactsProvider internal use only.
* <P>Type: INTEGER</P>
*
+ * @Deprecated
* @hide
*/
public static final String SUB_ID = "sub_id";
@@ -422,6 +435,19 @@
final ContentResolver resolver = context.getContentResolver();
int numberPresentation = PRESENTATION_ALLOWED;
+ TelecomManager tm = null;
+ try {
+ tm = TelecomManager.from(context);
+ } catch (UnsupportedOperationException e) {}
+
+ String accountAddress = null;
+ if (tm != null && accountHandle != null) {
+ PhoneAccount account = tm.getPhoneAccount(accountHandle);
+ if (account != null) {
+ accountAddress = account.getSubscriptionAddress().getSchemeSpecificPart();
+ }
+ }
+
// Remap network specified number presentation types
// PhoneConstants.PRESENTATION_xxx to calllog number presentation types
// Calls.PRESENTATION_xxx, in order to insulate the persistent calllog
@@ -463,6 +489,7 @@
}
values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
values.put(PHONE_ACCOUNT_ID, accountId);
+ values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
values.put(NEW, Integer.valueOf(1));
if (callType == MISSED_TYPE) {
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index d410622..df4d7e0 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -18,6 +18,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -383,7 +385,7 @@
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
- public void setContentView(int layoutResID) {
+ public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
}
@@ -444,7 +446,7 @@
* @return The view if found or null otherwise.
*/
@Nullable
- public View findViewById(int id) {
+ public View findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 06e9ce0..f0ad951 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -15,6 +15,7 @@
*/
package android.speech.tts;
+import android.annotation.RawRes;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
@@ -884,7 +885,7 @@
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
- public int addSpeech(String text, String packagename, int resourceId) {
+ public int addSpeech(String text, String packagename, @RawRes int resourceId) {
synchronized (mStartLock) {
mUtterances.put(text, makeResourceUri(packagename, resourceId));
return SUCCESS;
@@ -993,7 +994,7 @@
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
- public int addEarcon(String earcon, String packagename, int resourceId) {
+ public int addEarcon(String earcon, String packagename, @RawRes int resourceId) {
synchronized(mStartLock) {
mEarcons.put(earcon, makeResourceUri(packagename, resourceId));
return SUCCESS;
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 48bb5dd..1bb35f6 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -16,6 +16,7 @@
package android.text;
+import android.annotation.Nullable;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
@@ -457,7 +458,7 @@
* @param str the string to be examined
* @return true if str is null or zero length
*/
- public static boolean isEmpty(CharSequence str) {
+ public static boolean isEmpty(@Nullable CharSequence str) {
if (str == null || str.length() == 0)
return true;
else
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 3d6f8e6..856dd0b 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -16,6 +16,7 @@
package android.text.style;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -110,7 +111,7 @@
mSource = uri.toString();
}
- public ImageSpan(Context context, int resourceId) {
+ public ImageSpan(Context context, @DrawableRes int resourceId) {
this(context, resourceId, ALIGN_BOTTOM);
}
@@ -118,7 +119,7 @@
* @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
* {@link DynamicDrawableSpan#ALIGN_BASELINE}.
*/
- public ImageSpan(Context context, int resourceId, int verticalAlignment) {
+ public ImageSpan(Context context, @DrawableRes int resourceId, int verticalAlignment) {
super(verticalAlignment);
mContext = context;
mResourceId = resourceId;
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 74d4245..98aaa81 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -16,6 +16,8 @@
package android.util;
+import android.annotation.AnyRes;
+
/**
* Container for a dynamically typed data value. Primarily used with
* {@link android.content.res.Resources} for holding resource values.
@@ -178,6 +180,7 @@
public int assetCookie;
/** If Value came from a resource, this holds the corresponding resource id. */
+ @AnyRes
public int resourceId;
/** If Value came from a resource, these are the configurations for which
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index ae4b60f..a018138 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -17,6 +17,8 @@
package android.view;
+import android.annotation.StringRes;
+
/**
* Represents a contextual mode of the user interface. Action modes can be used to provide
* alternative interaction modes and replace parts of the normal UI until finished.
@@ -93,7 +95,7 @@
* @see #setTitle(CharSequence)
* @see #setCustomView(View)
*/
- public abstract void setTitle(int resId);
+ public abstract void setTitle(@StringRes int resId);
/**
* Set the subtitle of the action mode. This method will have no visible effect if
@@ -115,7 +117,7 @@
* @see #setSubtitle(CharSequence)
* @see #setCustomView(View)
*/
- public abstract void setSubtitle(int resId);
+ public abstract void setSubtitle(@StringRes int resId);
/**
* Set whether or not the title/subtitle display for this action mode
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index f41afcf..c8149d9 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -141,6 +141,19 @@
private long mFrameIntervalNanos;
/**
+ * Contains information about the current frame for jank-tracking,
+ * mainly timings of key events along with a bit of metadata about
+ * view tree state
+ *
+ * TODO: Is there a better home for this? Currently Choreographer
+ * is the only one with CALLBACK_ANIMATION start time, hence why this
+ * resides here.
+ *
+ * @hide
+ */
+ FrameInfo mFrameInfo = new FrameInfo();
+
+ /**
* Callback type: Input callback. Runs first.
* @hide
*/
@@ -513,6 +526,7 @@
return; // no work to do
}
+ long intendedFrameTimeNanos = frameTimeNanos;
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
@@ -541,12 +555,18 @@
return;
}
+ mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
}
+ mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
+
+ mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
+
+ mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
if (DEBUG) {
diff --git a/core/java/android/view/ContextMenu.java b/core/java/android/view/ContextMenu.java
index decabcb..85fe421 100644
--- a/core/java/android/view/ContextMenu.java
+++ b/core/java/android/view/ContextMenu.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.widget.AdapterView;
@@ -44,7 +46,7 @@
* @param titleRes The string resource identifier used for the title.
* @return This ContextMenu so additional setters can be called.
*/
- public ContextMenu setHeaderTitle(int titleRes);
+ public ContextMenu setHeaderTitle(@StringRes int titleRes);
/**
* Sets the context menu header's title to the title given in <var>title</var>.
@@ -61,7 +63,7 @@
* @param iconRes The resource identifier used for the icon.
* @return This ContextMenu so additional setters can be called.
*/
- public ContextMenu setHeaderIcon(int iconRes);
+ public ContextMenu setHeaderIcon(@DrawableRes int iconRes);
/**
* Sets the context menu header's icon to the icon given in <var>icon</var>
diff --git a/core/java/android/view/FrameInfo.java b/core/java/android/view/FrameInfo.java
new file mode 100644
index 0000000..c79547c
--- /dev/null
+++ b/core/java/android/view/FrameInfo.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class that contains all the timing information for the current frame. This
+ * is used in conjunction with the hardware renderer to provide
+ * continous-monitoring jank events
+ *
+ * All times in nanoseconds from CLOCK_MONOTONIC/System.nanoTime()
+ *
+ * To minimize overhead from System.nanoTime() calls we infer durations of
+ * things by knowing the ordering of the events. For example, to know how
+ * long layout & measure took it's displayListRecordStart - performTraversalsStart.
+ *
+ * These constants must be kept in sync with FrameInfo.h in libhwui and are
+ * used for indexing into AttachInfo's mFrameInfo long[], which is intended
+ * to be quick to pass down to native via JNI, hence a pre-packed format
+ *
+ * @hide
+ */
+final class FrameInfo {
+
+ long[] mFrameInfo = new long[9];
+
+ // Various flags set to provide extra metadata about the current frame
+ private static final int FLAGS = 0;
+
+ // Is this the first-draw following a window layout?
+ public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
+
+ @IntDef(flag = true, value = {
+ FLAG_WINDOW_LAYOUT_CHANGED })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrameInfoFlags {}
+
+ // The intended vsync time, unadjusted by jitter
+ private static final int INTENDED_VSYNC = 1;
+
+ // Jitter-adjusted vsync time, this is what was used as input into the
+ // animation & drawing system
+ private static final int VSYNC = 2;
+
+ // The time of the oldest input event
+ private static final int OLDEST_INPUT_EVENT = 3;
+
+ // The time of the newest input event
+ private static final int NEWEST_INPUT_EVENT = 4;
+
+ // When input event handling started
+ private static final int HANDLE_INPUT_START = 5;
+
+ // When animation evaluations started
+ private static final int ANIMATION_START = 6;
+
+ // When ViewRootImpl#performTraversals() started
+ private static final int PERFORM_TRAVERSALS_START = 7;
+
+ // When View:draw() started
+ private static final int DRAW_START = 8;
+
+ public void setVsync(long intendedVsync, long usedVsync) {
+ mFrameInfo[INTENDED_VSYNC] = intendedVsync;
+ mFrameInfo[VSYNC] = usedVsync;
+ mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
+ mFrameInfo[NEWEST_INPUT_EVENT] = 0;
+ mFrameInfo[FLAGS] = 0;
+ }
+
+ public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
+ if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
+ mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
+ }
+ if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
+ mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
+ }
+ }
+
+ public void markInputHandlingStart() {
+ mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
+ }
+
+ public void markAnimationsStart() {
+ mFrameInfo[ANIMATION_START] = System.nanoTime();
+ }
+
+ public void markPerformTraversalsStart() {
+ mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
+ }
+
+ public void markDrawStart() {
+ mFrameInfo[DRAW_START] = System.nanoTime();
+ }
+
+ public void addFlags(@FrameInfoFlags long flags) {
+ mFrameInfo[FLAGS] |= flags;
+ }
+
+}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c5c3f83..aa61885 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -278,7 +278,7 @@
/**
* Outputs extra debugging information in the specified file descriptor.
*/
- abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd);
+ abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args);
/**
* Loads system properties used by the renderer. This method is invoked
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index a5225cb..1014573 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
@@ -369,7 +370,7 @@
* this is the root View; otherwise it is the root of the inflated
* XML file.
*/
- public View inflate(int resource, @Nullable ViewGroup root) {
+ public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
@@ -410,7 +411,7 @@
* attachToRoot is true, this is root; otherwise it is the root of
* the inflated XML file.
*/
- public View inflate(int resource, @Nullable ViewGroup root, boolean attachToRoot) {
+ public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
final Resources res = getContext().getResources();
if (DEBUG) {
Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
diff --git a/core/java/android/view/Menu.java b/core/java/android/view/Menu.java
index 7157bc5..0c2e9cf 100644
--- a/core/java/android/view/Menu.java
+++ b/core/java/android/view/Menu.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.StringRes;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
@@ -148,7 +149,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added menu item.
*/
- public MenuItem add(int titleRes);
+ public MenuItem add(@StringRes int titleRes);
/**
* Add a new item to the menu. This item displays the given title for its
@@ -182,7 +183,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added menu item.
*/
- public MenuItem add(int groupId, int itemId, int order, int titleRes);
+ public MenuItem add(int groupId, int itemId, int order, @StringRes int titleRes);
/**
* Add a new sub-menu to the menu. This item displays the given title for
@@ -202,7 +203,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added sub-menu
*/
- SubMenu addSubMenu(final int titleRes);
+ SubMenu addSubMenu(@StringRes final int titleRes);
/**
* Add a new sub-menu to the menu. This item displays the given
@@ -239,7 +240,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added sub-menu
*/
- SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes);
+ SubMenu addSubMenu(int groupId, int itemId, int order, @StringRes int titleRes);
/**
* Add a group of menu items corresponding to actions that can be performed
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 5811c17..3492aa0 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.MenuRes;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
@@ -101,7 +102,7 @@
* @param menu The Menu to inflate into. The items and submenus will be
* added to this Menu.
*/
- public void inflate(int menuRes, Menu menu) {
+ public void inflate(@MenuRes int menuRes, Menu menu) {
XmlResourceParser parser = null;
try {
parser = mContext.getResources().getLayout(menuRes);
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index e706c9c..9e8b97e 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -16,6 +16,9 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
+import android.annotation.StringRes;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -165,7 +168,7 @@
* @see #setTitleCondensed(CharSequence)
*/
- public MenuItem setTitle(int title);
+ public MenuItem setTitle(@StringRes int title);
/**
* Retrieve the current title of the item.
@@ -214,7 +217,7 @@
* @param iconRes The new icon (as a resource ID) to be displayed.
* @return This Item so additional setters can be called.
*/
- public MenuItem setIcon(int iconRes);
+ public MenuItem setIcon(@DrawableRes int iconRes);
/**
* Returns the icon for this item as a Drawable (getting it from resources if it hasn't been
@@ -511,7 +514,7 @@
*
* @see #setShowAsAction(int)
*/
- public MenuItem setActionView(int resId);
+ public MenuItem setActionView(@LayoutRes int resId);
/**
* Returns the currently set action view for this menu item.
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index ca8a68a..c1498ec 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -25,7 +25,9 @@
import android.app.ActivityManagerNative;
import android.app.SearchManager;
import android.os.UserHandle;
+
import com.android.internal.R;
+import com.android.internal.view.ActionModeWrapper;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
import com.android.internal.view.menu.ContextMenuBuilder;
@@ -2689,72 +2691,78 @@
if (mode != null) {
mActionMode = mode;
} else {
- if (mActionModeView == null) {
- if (isFloating()) {
- // Use the action bar theme.
- final TypedValue outValue = new TypedValue();
- final Theme baseTheme = mContext.getTheme();
- baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
-
- final Context actionBarContext;
- if (outValue.resourceId != 0) {
- final Theme actionBarTheme = mContext.getResources().newTheme();
- actionBarTheme.setTo(baseTheme);
- actionBarTheme.applyStyle(outValue.resourceId, true);
-
- actionBarContext = new ContextThemeWrapper(mContext, 0);
- actionBarContext.getTheme().setTo(actionBarTheme);
- } else {
- actionBarContext = mContext;
- }
-
- mActionModeView = new ActionBarContextView(actionBarContext);
- mActionModePopup = new PopupWindow(actionBarContext, null,
- R.attr.actionModePopupWindowStyle);
- mActionModePopup.setWindowLayoutType(
- WindowManager.LayoutParams.TYPE_APPLICATION);
- mActionModePopup.setContentView(mActionModeView);
- mActionModePopup.setWidth(MATCH_PARENT);
-
- actionBarContext.getTheme().resolveAttribute(
- R.attr.actionBarSize, outValue, true);
- final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
- actionBarContext.getResources().getDisplayMetrics());
- mActionModeView.setContentHeight(height);
- mActionModePopup.setHeight(WRAP_CONTENT);
- mShowActionModePopup = new Runnable() {
- public void run() {
- mActionModePopup.showAtLocation(
- mActionModeView.getApplicationWindowToken(),
- Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
- }
- };
- } else {
- ViewStub stub = (ViewStub) findViewById(
- R.id.action_mode_bar_stub);
- if (stub != null) {
- mActionModeView = (ActionBarContextView) stub.inflate();
- }
- }
- }
-
if (mActionModeView != null) {
mActionModeView.killMode();
- mode = new StandaloneActionMode(mActionModeView.getContext(), mActionModeView,
- wrappedCallback, mActionModePopup == null);
- if (callback.onCreateActionMode(mode, mode.getMenu())) {
- mode.invalidate();
- mActionModeView.initForMode(mode);
- mActionModeView.setVisibility(View.VISIBLE);
- mActionMode = mode;
- if (mActionModePopup != null) {
- post(mShowActionModePopup);
+ }
+ ActionModeWrapper wrapperMode =
+ new ActionModeWrapper(mContext, wrappedCallback);
+ if (callback.onCreateActionMode(wrapperMode, wrapperMode.getMenu())) {
+ if (wrapperMode.getType() == ActionMode.TYPE_PRIMARY) {
+ if (mActionModeView == null) {
+ if (isFloating()) {
+ // Use the action bar theme.
+ final TypedValue outValue = new TypedValue();
+ final Theme baseTheme = mContext.getTheme();
+ baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
+
+ final Context actionBarContext;
+ if (outValue.resourceId != 0) {
+ final Theme actionBarTheme = mContext.getResources().newTheme();
+ actionBarTheme.setTo(baseTheme);
+ actionBarTheme.applyStyle(outValue.resourceId, true);
+
+ actionBarContext = new ContextThemeWrapper(mContext, 0);
+ actionBarContext.getTheme().setTo(actionBarTheme);
+ } else {
+ actionBarContext = mContext;
+ }
+
+ mActionModeView = new ActionBarContextView(actionBarContext);
+ mActionModePopup = new PopupWindow(actionBarContext, null,
+ R.attr.actionModePopupWindowStyle);
+ mActionModePopup.setWindowLayoutType(
+ WindowManager.LayoutParams.TYPE_APPLICATION);
+ mActionModePopup.setContentView(mActionModeView);
+ mActionModePopup.setWidth(MATCH_PARENT);
+
+ actionBarContext.getTheme().resolveAttribute(
+ R.attr.actionBarSize, outValue, true);
+ final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
+ actionBarContext.getResources().getDisplayMetrics());
+ mActionModeView.setContentHeight(height);
+ mActionModePopup.setHeight(WRAP_CONTENT);
+ mShowActionModePopup = new Runnable() {
+ public void run() {
+ mActionModePopup.showAtLocation(
+ mActionModeView.getApplicationWindowToken(),
+ Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
+ }
+ };
+ } else {
+ ViewStub stub = (ViewStub) findViewById(
+ R.id.action_mode_bar_stub);
+ if (stub != null) {
+ mActionModeView = (ActionBarContextView) stub.inflate();
+ }
+ }
}
- mActionModeView.sendAccessibilityEvent(
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- } else {
- mActionMode = null;
+ if (mActionModeView != null) {
+ wrapperMode.setActionModeView(mActionModeView);
+ wrapperMode.setFocusable(mActionModePopup == null);
+ wrapperMode.lockType();
+ wrapperMode.invalidate();
+ mActionModeView.initForMode(wrapperMode);
+ mActionModeView.setVisibility(View.VISIBLE);
+ mActionMode = wrapperMode;
+ if (mActionModePopup != null) {
+ post(mShowActionModePopup);
+ }
+ mActionModeView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
}
+ } else {
+ mActionMode = null;
}
}
if (mActionMode != null && getCallback() != null && !isDestroyed()) {
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 7dcad68..cf35ce5 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -18,6 +18,7 @@
import com.android.internal.util.XmlUtils;
+import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -192,7 +193,7 @@
* @throws Resources.NotFoundException if the resource was not found or the drawable
* linked in the resource was not found.
*/
- public static PointerIcon loadCustomIcon(Resources resources, int resourceId) {
+ public static PointerIcon loadCustomIcon(Resources resources, @XmlRes int resourceId) {
if (resources == null) {
throw new IllegalArgumentException("resources must not be null");
}
@@ -373,7 +374,7 @@
return true;
}
- private void loadResource(Context context, Resources resources, int resourceId) {
+ private void loadResource(Context context, Resources resources, @XmlRes int resourceId) {
final XmlResourceParser parser = resources.getXml(resourceId);
final int bitmapRes;
final float hotSpotX;
diff --git a/core/java/android/view/SubMenu.java b/core/java/android/view/SubMenu.java
index 196a183..38662b0 100644
--- a/core/java/android/view/SubMenu.java
+++ b/core/java/android/view/SubMenu.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.graphics.drawable.Drawable;
/**
@@ -38,7 +40,7 @@
* @param titleRes The string resource identifier used for the title.
* @return This SubMenu so additional setters can be called.
*/
- public SubMenu setHeaderTitle(int titleRes);
+ public SubMenu setHeaderTitle(@StringRes int titleRes);
/**
* Sets the submenu header's title to the title given in <var>title</var>.
@@ -55,7 +57,7 @@
* @param iconRes The resource identifier used for the icon.
* @return This SubMenu so additional setters can be called.
*/
- public SubMenu setHeaderIcon(int iconRes);
+ public SubMenu setHeaderIcon(@DrawableRes int iconRes);
/**
* Sets the submenu header's icon to the icon given in <var>icon</var>
@@ -88,7 +90,7 @@
* @param iconRes The new icon (as a resource ID) to be displayed.
* @return This SubMenu so additional setters can be called.
*/
- public SubMenu setIcon(int iconRes);
+ public SubMenu setIcon(@DrawableRes int iconRes);
/**
* Change the icon associated with this submenu's item in its parent menu.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index ad4a048..df0838f 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,8 +16,7 @@
package android.view;
-import com.android.internal.R;
-
+import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -27,16 +26,18 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.Trace;
import android.util.Log;
import android.util.LongSparseArray;
-import android.util.TimeUtils;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
+import com.android.internal.R;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashSet;
@@ -74,6 +75,14 @@
PROFILE_PROPERTY_VISUALIZE_BARS,
};
+ private static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
+ private static final int FLAG_DUMP_RESET = 1 << 1;
+
+ @IntDef(flag = true, value = {
+ FLAG_DUMP_FRAMESTATS, FLAG_DUMP_RESET })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DumpFlags {}
+
// Size of the rendered content.
private int mWidth, mHeight;
@@ -93,12 +102,12 @@
private final float mLightRadius;
private final int mAmbientShadowAlpha;
private final int mSpotShadowAlpha;
+ private final float mDensity;
private long mNativeProxy;
private boolean mInitialized = false;
private RenderNode mRootNode;
private Choreographer mChoreographer;
- private boolean mProfilingEnabled;
private boolean mRootNodeNeedsUpdate;
ThreadedRenderer(Context context, boolean translucent) {
@@ -110,6 +119,7 @@
(int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
a.recycle();
+ mDensity = context.getResources().getDisplayMetrics().density;
long rootNodePtr = nCreateRootRenderNode();
mRootNode = RenderNode.adopt(rootNodePtr);
@@ -214,7 +224,7 @@
mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight,
lightX, mLightY, mLightZ, mLightRadius,
- mAmbientShadowAlpha, mSpotShadowAlpha);
+ mAmbientShadowAlpha, mSpotShadowAlpha, mDensity);
}
@Override
@@ -233,32 +243,25 @@
}
@Override
- void dumpGfxInfo(PrintWriter pw, FileDescriptor fd) {
+ void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
pw.flush();
- nDumpProfileInfo(mNativeProxy, fd);
- }
-
- private static int search(String[] values, String value) {
- for (int i = 0; i < values.length; i++) {
- if (values[i].equals(value)) return i;
+ int flags = 0;
+ for (int i = 0; i < args.length; i++) {
+ switch (args[i]) {
+ case "framestats":
+ flags |= FLAG_DUMP_FRAMESTATS;
+ break;
+ case "reset":
+ flags |= FLAG_DUMP_RESET;
+ break;
+ }
}
- return -1;
- }
-
- private static boolean checkIfProfilingRequested() {
- String profiling = SystemProperties.get(HardwareRenderer.PROFILE_PROPERTY);
- int graphType = search(VISUALIZERS, profiling);
- return (graphType >= 0) || Boolean.parseBoolean(profiling);
+ nDumpProfileInfo(mNativeProxy, fd, flags);
}
@Override
boolean loadSystemProperties() {
boolean changed = nLoadSystemProperties(mNativeProxy);
- boolean wantProfiling = checkIfProfilingRequested();
- if (wantProfiling != mProfilingEnabled) {
- mProfilingEnabled = wantProfiling;
- changed = true;
- }
if (changed) {
invalidateRoot();
}
@@ -307,20 +310,12 @@
@Override
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
attachInfo.mIgnoreDirtyState = true;
- long frameTimeNanos = mChoreographer.getFrameTimeNanos();
- attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS;
- long recordDuration = 0;
- if (mProfilingEnabled) {
- recordDuration = System.nanoTime();
- }
+ final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
+ choreographer.mFrameInfo.markDrawStart();
updateRootDisplayList(view, callbacks);
- if (mProfilingEnabled) {
- recordDuration = System.nanoTime() - recordDuration;
- }
-
attachInfo.mIgnoreDirtyState = false;
// register animating rendernodes which started animating prior to renderer
@@ -337,8 +332,8 @@
attachInfo.mPendingAnimatingRenderNodes = null;
}
- int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
- recordDuration, view.getResources().getDisplayMetrics().density);
+ final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
+ int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false);
attachInfo.mViewRootImpl.mSurface.release();
@@ -500,10 +495,9 @@
private static native boolean nPauseSurface(long nativeProxy, Surface window);
private static native void nSetup(long nativeProxy, int width, int height,
float lightX, float lightY, float lightZ, float lightRadius,
- int ambientShadowAlpha, int spotShadowAlpha);
+ int ambientShadowAlpha, int spotShadowAlpha, float density);
private static native void nSetOpaque(long nativeProxy, boolean opaque);
- private static native int nSyncAndDrawFrame(long nativeProxy,
- long frameTimeNanos, long recordDuration, float density);
+ private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
private static native void nDestroy(long nativeProxy);
private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
@@ -523,5 +517,6 @@
private static native void nStopDrawing(long nativeProxy);
private static native void nNotifyFramePending(long nativeProxy);
- private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd);
+ private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
+ @DumpFlags int dumpFlags);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ad5d651..f99d2d5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -18,6 +18,8 @@
import android.animation.AnimatorInflater;
import android.animation.StateListAnimator;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1593,6 +1595,7 @@
* @see #setId(int)
* @see #getId()
*/
+ @IdRes
@ViewDebug.ExportedProperty(resolveId = true)
int mID = NO_ID;
@@ -6062,7 +6065,7 @@
* @param id The labeled view id.
*/
@RemotableViewMethod
- public void setLabelFor(int id) {
+ public void setLabelFor(@IdRes int id) {
if (mLabelForId == id) {
return;
}
@@ -16242,7 +16245,7 @@
* @attr ref android.R.styleable#View_background
*/
@RemotableViewMethod
- public void setBackgroundResource(int resid) {
+ public void setBackgroundResource(@DrawableRes int resid) {
if (resid != 0 && resid == mBackgroundResource) {
return;
}
@@ -17070,7 +17073,7 @@
* @param id the id of the view to be found
* @return the view of the specified id, null if cannot be found
*/
- protected View findViewTraversal(int id) {
+ protected View findViewTraversal(@IdRes int id) {
if (id == mID) {
return this;
}
@@ -17110,7 +17113,7 @@
* @return The view that has the given id in the hierarchy or null
*/
@Nullable
- public final View findViewById(int id) {
+ public final View findViewById(@IdRes int id) {
if (id < 0) {
return null;
}
@@ -17225,7 +17228,7 @@
*
* @attr ref android.R.styleable#View_id
*/
- public void setId(int id) {
+ public void setId(@IdRes int id) {
mID = id;
if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
mID = generateViewId();
@@ -17265,6 +17268,7 @@
* @see #findViewById(int)
* @attr ref android.R.styleable#View_id
*/
+ @IdRes
@ViewDebug.CapturedViewProperty
public int getId() {
return mID;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 504a758..a49d8c3 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -17,6 +17,7 @@
package android.view;
import android.animation.LayoutTransition;
+import android.annotation.IdRes;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
@@ -3612,7 +3613,7 @@
* {@hide}
*/
@Override
- protected View findViewTraversal(int id) {
+ protected View findViewTraversal(@IdRes int id) {
if (id == mID) {
return this;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 24fae8a..f392682 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -56,6 +56,7 @@
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
+import android.util.TimeUtils;
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
@@ -1342,7 +1343,7 @@
boolean insetsChanged = false;
- boolean layoutRequested = mLayoutRequested && !mStopped;
+ boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
if (layoutRequested) {
final Resources res = mView.getContext().getResources();
@@ -1513,6 +1514,7 @@
// to resume them
mDirty.set(0, 0, mWidth, mHeight);
}
+ mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
}
final int surfaceGenerationId = mSurface.getGenerationId();
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
@@ -1774,7 +1776,7 @@
}
}
- if (!mStopped) {
+ if (!mStopped || mReportNextDraw) {
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
@@ -1847,7 +1849,7 @@
}
}
- final boolean didLayout = layoutRequested && !mStopped;
+ final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
boolean triggerGlobalLayoutListener = didLayout
|| mAttachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
@@ -2516,6 +2518,9 @@
}
}
+ mAttachInfo.mDrawingTime =
+ mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
+
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
// If accessibility focus moved, always invalidate the root.
@@ -2635,7 +2640,6 @@
dirty.setEmpty();
mIsAnimating = false;
- attachInfo.mDrawingTime = SystemClock.uptimeMillis();
mView.mPrivateFlags |= View.PFLAG_DRAWN;
if (DEBUG_DRAW) {
@@ -5789,6 +5793,16 @@
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
+ long eventTime = q.mEvent.getEventTimeNano();
+ long oldestEventTime = eventTime;
+ if (q.mEvent instanceof MotionEvent) {
+ MotionEvent me = (MotionEvent)q.mEvent;
+ if (me.getHistorySize() > 0) {
+ oldestEventTime = me.getHistoricalEventTimeNano(0);
+ }
+ }
+ mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
+
deliverInputEvent(q);
}
diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java
index 9f9ed5b..ec852e8 100644
--- a/core/java/android/view/ViewStub.java
+++ b/core/java/android/view/ViewStub.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -87,7 +89,7 @@
* @param context The application's environment.
* @param layoutResource The reference to a layout resource that will be inflated.
*/
- public ViewStub(Context context, int layoutResource) {
+ public ViewStub(Context context, @LayoutRes int layoutResource) {
this(context, null);
mLayoutResource = layoutResource;
@@ -125,6 +127,7 @@
* @see #setInflatedId(int)
* @attr ref android.R.styleable#ViewStub_inflatedId
*/
+ @IdRes
public int getInflatedId() {
return mInflatedId;
}
@@ -140,7 +143,7 @@
* @attr ref android.R.styleable#ViewStub_inflatedId
*/
@android.view.RemotableViewMethod
- public void setInflatedId(int inflatedId) {
+ public void setInflatedId(@IdRes int inflatedId) {
mInflatedId = inflatedId;
}
@@ -156,6 +159,7 @@
* @see #inflate()
* @attr ref android.R.styleable#ViewStub_layout
*/
+ @LayoutRes
public int getLayoutResource() {
return mLayoutResource;
}
@@ -173,7 +177,7 @@
* @attr ref android.R.styleable#ViewStub_layout
*/
@android.view.RemotableViewMethod
- public void setLayoutResource(int layoutResource) {
+ public void setLayoutResource(@LayoutRes int layoutResource) {
mLayoutResource = layoutResource;
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 8964862..e332135 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -16,6 +16,9 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -985,7 +988,7 @@
* @return The view if found or null otherwise.
*/
@Nullable
- public View findViewById(int id) {
+ public View findViewById(@IdRes int id) {
return getDecorView().findViewById(id);
}
@@ -998,7 +1001,7 @@
* @param layoutResID Resource ID to be inflated.
* @see #setContentView(View, android.view.ViewGroup.LayoutParams)
*/
- public abstract void setContentView(int layoutResID);
+ public abstract void setContentView(@LayoutRes int layoutResID);
/**
* Convenience for
@@ -1128,7 +1131,7 @@
* @param resId The resource identifier of a drawable resource which will
* be installed as the new background.
*/
- public void setBackgroundDrawableResource(int resId) {
+ public void setBackgroundDrawableResource(@DrawableRes int resId) {
setBackgroundDrawable(mContext.getDrawable(resId));
}
@@ -1144,7 +1147,7 @@
/**
* Set the value for a drawable feature of this window, from a resource
- * identifier. You must have called requestFeauture(featureId) before
+ * identifier. You must have called requestFeature(featureId) before
* calling this function.
*
* @see android.content.res.Resources#getDrawable(int)
@@ -1153,7 +1156,7 @@
* constant by Window.
* @param resId Resource identifier of the desired image.
*/
- public abstract void setFeatureDrawableResource(int featureId, int resId);
+ public abstract void setFeatureDrawableResource(int featureId, @DrawableRes int resId);
/**
* Set the value for a drawable feature of this window, from a URI. You
@@ -1423,7 +1426,7 @@
*
* @param resId resource ID of a drawable to set
*/
- public void setIcon(int resId) { }
+ public void setIcon(@DrawableRes int resId) { }
/**
* Set the default icon for this window.
@@ -1432,7 +1435,7 @@
*
* @hide
*/
- public void setDefaultIcon(int resId) { }
+ public void setDefaultIcon(@DrawableRes int resId) { }
/**
* Set the logo for this window. A logo is often shown in place of an
@@ -1441,7 +1444,7 @@
*
* @param resId resource ID of a drawable to set
*/
- public void setLogo(int resId) { }
+ public void setLogo(@DrawableRes int resId) { }
/**
* Set the default logo for this window.
@@ -1450,7 +1453,7 @@
*
* @hide
*/
- public void setDefaultLogo(int resId) { }
+ public void setDefaultLogo(@DrawableRes int resId) { }
/**
* Set focus locally. The window should have the
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 279627a..1cebe3f 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -492,7 +492,7 @@
}
}
- public void dumpGfxInfo(FileDescriptor fd) {
+ public void dumpGfxInfo(FileDescriptor fd, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
try {
@@ -509,7 +509,7 @@
HardwareRenderer renderer =
root.getView().mAttachInfo.mHardwareRenderer;
if (renderer != null) {
- renderer.dumpGfxInfo(pw, fd);
+ renderer.dumpGfxInfo(pw, fd, args);
}
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 3f35612..9199af1 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -365,6 +365,11 @@
* @return true if window is on default display.
*/
public boolean isDefaultDisplay();
+
+ /**
+ * Check whether the window is currently dimming.
+ */
+ public boolean isDimming();
}
/**
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 606c83e..4d1209a 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -19,6 +19,8 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.AnimRes;
+import android.annotation.InterpolatorRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -65,7 +67,7 @@
* @return The animation object reference by the specified id
* @throws NotFoundException when the animation cannot be loaded
*/
- public static Animation loadAnimation(Context context, int id)
+ public static Animation loadAnimation(Context context, @AnimRes int id)
throws NotFoundException {
XmlResourceParser parser = null;
@@ -143,7 +145,7 @@
* @return The animation object reference by the specified id
* @throws NotFoundException when the layout animation controller cannot be loaded
*/
- public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
+ public static LayoutAnimationController loadLayoutAnimation(Context context, @AnimRes int id)
throws NotFoundException {
XmlResourceParser parser = null;
@@ -266,7 +268,8 @@
* @return The animation object reference by the specified id
* @throws NotFoundException
*/
- public static Interpolator loadInterpolator(Context context, int id) throws NotFoundException {
+ public static Interpolator loadInterpolator(Context context, @InterpolatorRes int id)
+ throws NotFoundException {
XmlResourceParser parser = null;
try {
parser = context.getResources().getAnimation(id);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index e87a117..164283d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -2712,7 +2713,7 @@
*
* @attr ref android.R.styleable#AbsListView_listSelector
*/
- public void setSelector(int resID) {
+ public void setSelector(@DrawableRes int resID) {
setSelector(getContext().getDrawable(resID));
}
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index f9af2f9..f34ad71 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -334,7 +335,7 @@
*
* @param resourceId The content description resource id.
*/
- public void setExpandActivityOverflowButtonContentDescription(int resourceId) {
+ public void setExpandActivityOverflowButtonContentDescription(@StringRes int resourceId) {
CharSequence contentDescription = mContext.getString(resourceId);
mExpandActivityOverflowButtonImage.setContentDescription(contentDescription);
}
@@ -514,7 +515,7 @@
*
* @param resourceId The resource id.
*/
- public void setDefaultActionButtonContentDescription(int resourceId) {
+ public void setDefaultActionButtonContentDescription(@StringRes int resourceId) {
mDefaultActionButtonContentDescription = resourceId;
}
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index aff5e29..89e508f 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -16,6 +16,9 @@
package android.widget;
+import android.annotation.ArrayRes;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
@@ -106,7 +109,7 @@
* @param resource The resource ID for a layout file containing a TextView to use when
* instantiating views.
*/
- public ArrayAdapter(Context context, int resource) {
+ public ArrayAdapter(Context context, @LayoutRes int resource) {
this(context, resource, 0, new ArrayList<T>());
}
@@ -118,7 +121,7 @@
* instantiating views.
* @param textViewResourceId The id of the TextView within the layout resource to be populated
*/
- public ArrayAdapter(Context context, int resource, int textViewResourceId) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId) {
this(context, resource, textViewResourceId, new ArrayList<T>());
}
@@ -130,7 +133,7 @@
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int resource, T[] objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, T[] objects) {
this(context, resource, 0, Arrays.asList(objects));
}
@@ -143,7 +146,7 @@
* @param textViewResourceId The id of the TextView within the layout resource to be populated
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId, T[] objects) {
this(context, resource, textViewResourceId, Arrays.asList(objects));
}
@@ -155,7 +158,7 @@
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int resource, List<T> objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, List<T> objects) {
this(context, resource, 0, objects);
}
@@ -405,7 +408,7 @@
* @param resource the layout resource defining the drop down views
* @see #getDropDownView(int, android.view.View, android.view.ViewGroup)
*/
- public void setDropDownViewResource(int resource) {
+ public void setDropDownViewResource(@LayoutRes int resource) {
this.mDropDownResource = resource;
}
@@ -457,7 +460,7 @@
* @return An ArrayAdapter<CharSequence>.
*/
public static ArrayAdapter<CharSequence> createFromResource(Context context,
- int textArrayResId, int textViewResId) {
+ @ArrayRes int textArrayResId, @LayoutRes int textViewResId) {
CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
return new ArrayAdapter<CharSequence>(context, textViewResId, strings);
}
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index e6392b9..01767d5 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
@@ -356,7 +357,7 @@
*
* @attr ref android.R.styleable#PopupWindow_popupBackground
*/
- public void setDropDownBackgroundResource(int id) {
+ public void setDropDownBackgroundResource(@DrawableRes int id) {
mPopup.setBackgroundDrawable(getContext().getDrawable(id));
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 5e43916..47fb8a7 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.annotation.Widget;
import android.content.Context;
import android.content.res.Configuration;
@@ -253,7 +254,7 @@
*
* @attr ref android.R.styleable#CalendarView_selectedDateVerticalBar
*/
- public void setSelectedDateVerticalBar(int resourceId) {
+ public void setSelectedDateVerticalBar(@DrawableRes int resourceId) {
mDelegate.setSelectedDateVerticalBar(resourceId);
}
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 344d00a..84f0ee5 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -32,7 +33,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-
/**
* An extension to TextView that supports the {@link android.widget.Checkable} interface.
* This is useful when used in a {@link android.widget.ListView ListView} where the it's
@@ -141,7 +141,7 @@
*
* @attr ref android.R.styleable#CheckedTextView_checkMark
*/
- public void setCheckMarkDrawable(int resid) {
+ public void setCheckMarkDrawable(@DrawableRes int resid) {
if (resid != 0 && resid == mCheckMarkResource) {
return;
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index f2afeeb..dbf82b6 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -21,6 +21,7 @@
import android.graphics.PorterDuff;
import com.android.internal.R;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 4752594..8601d2b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -50,6 +50,7 @@
import android.inputmethodservice.ExtractEditText;
import android.os.Bundle;
import android.os.Handler;
+import android.os.ParcelableParcel;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.DynamicLayout;
@@ -118,15 +119,18 @@
*/
public class Editor {
private static final String TAG = "Editor";
- static final boolean DEBUG_UNDO = false;
+ private static final boolean DEBUG_UNDO = false;
static final int BLINK = 500;
private static final float[] TEMP_POSITION = new float[2];
private static int DRAG_SHADOW_MAX_TEXT_LENGTH = 20;
+ // Tag used when the Editor maintains its own separate UndoManager.
+ private static final String UNDO_OWNER_TAG = "Editor";
- UndoManager mUndoManager;
- UndoOwner mUndoOwner;
- InputFilter mUndoInputFilter;
+ // Each Editor manages its own undo stack.
+ private final UndoManager mUndoManager = new UndoManager();
+ private UndoOwner mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
+ final InputFilter mUndoInputFilter = new UndoInputFilter(this);
// Cursor Controllers.
InsertionPointCursorController mInsertionPointCursorController;
@@ -222,6 +226,39 @@
Editor(TextView textView) {
mTextView = textView;
+ // Synchronize the filter list, which places the undo input filter at the end.
+ mTextView.setFilters(mTextView.getFilters());
+ }
+
+ ParcelableParcel saveInstanceState() {
+ // For now there is only undo state.
+ return (ParcelableParcel) mUndoManager.saveInstanceState();
+ }
+
+ void restoreInstanceState(ParcelableParcel state) {
+ mUndoManager.restoreInstanceState(state);
+ // Re-associate this object as the owner of undo state.
+ mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
+ }
+
+ boolean canUndo() {
+ UndoOwner[] owners = { mUndoOwner };
+ return mUndoManager.countUndos(owners) > 0;
+ }
+
+ boolean canRedo() {
+ UndoOwner[] owners = { mUndoOwner };
+ return mUndoManager.countRedos(owners) > 0;
+ }
+
+ void undo() {
+ UndoOwner[] owners = { mUndoOwner };
+ mUndoManager.undo(owners, 1); // Undo 1 action.
+ }
+
+ void redo() {
+ UndoOwner[] owners = { mUndoOwner };
+ mUndoManager.redo(owners, 1); // Redo 1 action.
}
void onAttachedToWindow() {
@@ -1706,7 +1743,7 @@
/**
* Called by the framework in response to a text auto-correction (such as fixing a typo using a
- * a dictionnary) from the current input method, provided by it calling
+ * a dictionary) from the current input method, provided by it calling
* {@link InputConnection#commitCorrection} InputConnection.commitCorrection()}. The default
* implementation flashes the background of the corrected word to provide feedback to the user.
*
@@ -4161,8 +4198,12 @@
int mChangedStart, mChangedEnd, mChangedDelta;
}
+ /**
+ * An InputFilter that monitors text input to maintain undo history. It does not modify the
+ * text being typed (and hence always returns null from the filter() method).
+ */
public static class UndoInputFilter implements InputFilter {
- final Editor mEditor;
+ private final Editor mEditor;
public UndoInputFilter(Editor editor) {
mEditor = editor;
@@ -4192,6 +4233,8 @@
// The current operation is an add... are we adding more? We are adding
// more if we are either appending new text to the end of the last edit or
// completely replacing some or all of the last edit.
+ // TODO: This sequence doesn't work right: a, left-arrow, b, undo, undo.
+ // The two edits are incorrectly merged, so there is only one undo available.
if (start < end && ((dstart >= op.mRangeStart && dend <= op.mRangeEnd)
|| (dstart == op.mRangeEnd && dend == op.mRangeEnd))) {
op.mRangeEnd = dstart + (end-start);
@@ -4245,7 +4288,10 @@
}
}
- public static class TextModifyOperation extends UndoOperation<TextView> {
+ /**
+ * An operation to undo a single "edit" to a text view.
+ */
+ public static class TextModifyOperation extends UndoOperation<Editor> {
int mRangeStart, mRangeEnd;
CharSequence mOldText;
@@ -4277,8 +4323,8 @@
private void swapText() {
// Both undo and redo involves swapping the contents of the range
// in the text view with our local text.
- TextView tv = getOwnerData();
- Editable editable = (Editable)tv.getText();
+ Editor editor = getOwnerData();
+ Editable editable = (Editable)editor.mTextView.getText();
CharSequence curText;
if (mRangeStart >= mRangeEnd) {
curText = null;
@@ -4309,14 +4355,17 @@
public static final Parcelable.ClassLoaderCreator<TextModifyOperation> CREATOR
= new Parcelable.ClassLoaderCreator<TextModifyOperation>() {
+ @Override
public TextModifyOperation createFromParcel(Parcel in) {
return new TextModifyOperation(in, null);
}
+ @Override
public TextModifyOperation createFromParcel(Parcel in, ClassLoader loader) {
return new TextModifyOperation(in, loader);
}
+ @Override
public TextModifyOperation[] newArray(int size) {
return new TextModifyOperation[size];
}
diff --git a/core/java/android/widget/ImageSwitcher.java b/core/java/android/widget/ImageSwitcher.java
index 80e908a..81636a7 100644
--- a/core/java/android/widget/ImageSwitcher.java
+++ b/core/java/android/widget/ImageSwitcher.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -23,7 +24,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-
public class ImageSwitcher extends ViewSwitcher
{
public ImageSwitcher(Context context)
@@ -35,7 +35,7 @@
super(context, attrs);
}
- public void setImageResource(int resid)
+ public void setImageResource(@DrawableRes int resid)
{
ImageView image = (ImageView)this.getNextView();
image.setImageResource(resid);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index dd9bdb66..9831dca 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
@@ -387,7 +388,7 @@
* @attr ref android.R.styleable#ImageView_src
*/
@android.view.RemotableViewMethod
- public void setImageResource(int resId) {
+ public void setImageResource(@DrawableRes int resId) {
// The resource configuration may have changed, so we should always
// try to load the resource even if the resId hasn't changed.
final int oldWidth = mDrawableWidth;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 0aaef6d..f9c7faa 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -21,6 +21,7 @@
import com.android.internal.util.Predicate;
import com.google.android.collect.Lists;
+import android.annotation.IdRes;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -3630,7 +3631,7 @@
* First look in our children, then in any header and footer views that may be scrolled off.
*/
@Override
- protected View findViewTraversal(int id) {
+ protected View findViewTraversal(@IdRes int id) {
View v;
v = super.findViewTraversal(id);
if (v == null) {
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index 06ac1c3..1507dfb 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -22,6 +22,7 @@
import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.SubMenuBuilder;
+import android.annotation.MenuRes;
import android.content.Context;
import android.view.Gravity;
import android.view.Menu;
@@ -205,7 +206,7 @@
* popupMenu.getMenuInflater().inflate(menuRes, popupMenu.getMenu()).
* @param menuRes Menu resource to inflate
*/
- public void inflate(int menuRes) {
+ public void inflate(@MenuRes int menuRes) {
getMenuInflater().inflate(menuRes, mMenu);
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5b0745e..406a274 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -21,6 +21,7 @@
import com.android.internal.R;
+import android.annotation.InterpolatorRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
@@ -1508,7 +1509,7 @@
* @param context The application environment
* @param resID The resource identifier of the interpolator to load
*/
- public void setInterpolator(Context context, int resID) {
+ public void setInterpolator(Context context, @InterpolatorRes int resID) {
setInterpolator(AnimationUtils.loadInterpolator(context, resID));
}
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index f04bb3d..6586d11 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.IdRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -151,7 +152,7 @@
* @see #getCheckedRadioButtonId()
* @see #clearCheck()
*/
- public void check(int id) {
+ public void check(@IdRes int id) {
// don't even bother
if (id != -1 && (id == mCheckedId)) {
return;
@@ -168,7 +169,7 @@
setCheckedId(id);
}
- private void setCheckedId(int id) {
+ private void setCheckedId(@IdRes int id) {
mCheckedId = id;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
@@ -193,6 +194,7 @@
*
* @attr ref android.R.styleable#RadioGroup_checkedButton
*/
+ @IdRes
public int getCheckedRadioButtonId() {
return mCheckedId;
}
@@ -331,7 +333,7 @@
* @param group the group in which the checked radio button has changed
* @param checkedId the unique identifier of the newly checked radio button
*/
- public void onCheckedChanged(RadioGroup group, int checkedId);
+ public void onCheckedChanged(RadioGroup group, @IdRes int checkedId);
}
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 6ee2b4c..f0bc303 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.annotation.Widget;
import android.app.AlertDialog;
@@ -46,7 +47,6 @@
import android.widget.ListPopupWindow.ForwardingListener;
import android.widget.PopupWindow.OnDismissListener;
-
/**
* A view that displays one child at a time and lets the user pick among them.
* The items in the Spinner come from the {@link Adapter} associated with
@@ -331,7 +331,7 @@
*
* @attr ref android.R.styleable#Spinner_popupBackground
*/
- public void setPopupBackgroundResource(int resId) {
+ public void setPopupBackgroundResource(@DrawableRes int resId) {
setPopupBackgroundDrawable(getPopupContext().getDrawable(resId));
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index b959ddc..ce1834e 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -17,7 +17,9 @@
package android.widget;
import android.animation.ObjectAnimator;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
+import android.annotation.StyleRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -263,7 +265,7 @@
*
* @attr ref android.R.styleable#Switch_switchTextAppearance
*/
- public void setSwitchTextAppearance(Context context, int resid) {
+ public void setSwitchTextAppearance(Context context, @StyleRes int resid) {
TypedArray appearance =
context.obtainStyledAttributes(resid,
com.android.internal.R.styleable.TextAppearance);
@@ -471,7 +473,7 @@
*
* @attr ref android.R.styleable#Switch_track
*/
- public void setTrackResource(int resId) {
+ public void setTrackResource(@DrawableRes int resId) {
setTrackDrawable(getContext().getDrawable(resId));
}
@@ -593,7 +595,7 @@
*
* @attr ref android.R.styleable#Switch_thumb
*/
- public void setThumbResource(int resId) {
+ public void setThumbResource(@DrawableRes int resId) {
setThumbDrawable(getContext().getDrawable(resId));
}
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 88ecb13..f90a0a7 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -17,6 +17,7 @@
package android.widget;
import android.R;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -244,7 +245,7 @@
* @param resId the resource identifier of the drawable to use as a
* divider.
*/
- public void setDividerDrawable(int resId) {
+ public void setDividerDrawable(@DrawableRes int resId) {
setDividerDrawable(mContext.getDrawable(resId));
}
@@ -265,7 +266,7 @@
* @param resId the resource identifier of the drawable to use as the
* left strip drawable
*/
- public void setLeftStripDrawable(int resId) {
+ public void setLeftStripDrawable(@DrawableRes int resId) {
setLeftStripDrawable(mContext.getDrawable(resId));
}
@@ -286,7 +287,7 @@
* @param resId the resource identifier of the drawable to use as the
* right strip drawable
*/
- public void setRightStripDrawable(int resId) {
+ public void setRightStripDrawable(@DrawableRes int resId) {
setRightStripDrawable(mContext.getDrawable(resId));
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 848c1c0..9297731 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,8 +17,12 @@
package android.widget;
import android.R;
+import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.annotation.StyleRes;
+import android.annotation.XmlRes;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -43,6 +47,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ParcelableParcel;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -1608,7 +1613,8 @@
* @hide
*/
public final UndoManager getUndoManager() {
- return mEditor == null ? null : mEditor.mUndoManager;
+ // TODO: Consider supporting a global undo manager.
+ throw new UnsupportedOperationException("not implemented");
}
/**
@@ -1626,22 +1632,12 @@
* @hide
*/
public final void setUndoManager(UndoManager undoManager, String tag) {
- if (undoManager != null) {
- createEditorIfNeeded();
- mEditor.mUndoManager = undoManager;
- mEditor.mUndoOwner = undoManager.getOwner(tag, this);
- mEditor.mUndoInputFilter = new Editor.UndoInputFilter(mEditor);
- if (!(mText instanceof Editable)) {
- setText(mText, BufferType.EDITABLE);
- }
-
- setFilters((Editable) mText, mFilters);
- } else if (mEditor != null) {
- // XXX need to destroy all associated state.
- mEditor.mUndoManager = null;
- mEditor.mUndoOwner = null;
- mEditor.mUndoInputFilter = null;
- }
+ // TODO: Consider supporting a global undo manager. An implementation will need to:
+ // * createEditorIfNeeded()
+ // * Promote to BufferType.EDITABLE if needed.
+ // * Update the UndoManager and UndoOwner.
+ // Likewise it will need to be able to restore the default UndoManager.
+ throw new UnsupportedOperationException("not implemented");
}
/**
@@ -2173,7 +2169,8 @@
* @attr ref android.R.styleable#TextView_drawableBottom
*/
@android.view.RemotableViewMethod
- public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {
+ public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left,
+ @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
final Context context = getContext();
setCompoundDrawablesWithIntrinsicBounds(left != 0 ? context.getDrawable(left) : null,
top != 0 ? context.getDrawable(top) : null,
@@ -2374,8 +2371,8 @@
* @attr ref android.R.styleable#TextView_drawableBottom
*/
@android.view.RemotableViewMethod
- public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
- int bottom) {
+ public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start,
+ @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
final Context context = getContext();
setCompoundDrawablesRelativeWithIntrinsicBounds(
start != 0 ? context.getDrawable(start) : null,
@@ -2643,7 +2640,7 @@
* Sets the text color, size, style, hint color, and highlight color
* from the specified TextAppearance resource.
*/
- public void setTextAppearance(Context context, int resid) {
+ public void setTextAppearance(Context context, @StyleRes int resid) {
TypedArray appearance =
context.obtainStyledAttributes(resid,
com.android.internal.R.styleable.TextAppearance);
@@ -3894,6 +3891,9 @@
ss.error = getError();
+ if (mEditor != null) {
+ ss.editorState = mEditor.saveInstanceState();
+ }
return ss;
}
@@ -3963,6 +3963,11 @@
}
});
}
+
+ if (ss.editorState != null) {
+ createEditorIfNeeded();
+ mEditor.restoreInstanceState(ss.editorState);
+ }
}
/**
@@ -4267,11 +4272,11 @@
}
@android.view.RemotableViewMethod
- public final void setText(int resid) {
+ public final void setText(@StringRes int resid) {
setText(getContext().getResources().getText(resid));
}
- public final void setText(int resid, BufferType type) {
+ public final void setText(@StringRes int resid, BufferType type) {
setText(getContext().getResources().getText(resid), type);
}
@@ -4307,7 +4312,7 @@
* @attr ref android.R.styleable#TextView_hint
*/
@android.view.RemotableViewMethod
- public final void setHint(int resid) {
+ public final void setHint(@StringRes int resid) {
setHint(getContext().getResources().getText(resid));
}
@@ -4711,7 +4716,7 @@
* @see EditorInfo#extras
* @attr ref android.R.styleable#TextView_editorExtras
*/
- public void setInputExtras(int xmlResId) throws XmlPullParserException, IOException {
+ public void setInputExtras(@XmlRes int xmlResId) throws XmlPullParserException, IOException {
createEditorIfNeeded();
XmlResourceParser parser = getResources().getXml(xmlResId);
mEditor.createInputContentTypeIfNeeded();
@@ -8370,14 +8375,19 @@
@Override
public boolean onKeyShortcut(int keyCode, KeyEvent event) {
- final int filteredMetaState = event.getMetaState() & ~KeyEvent.META_CTRL_MASK;
- if (KeyEvent.metaStateHasNoModifiers(filteredMetaState)) {
+ if (event.hasModifiers(KeyEvent.META_CTRL_ON)) {
+ // Handle Ctrl-only shortcuts.
switch (keyCode) {
case KeyEvent.KEYCODE_A:
if (canSelectText()) {
return onTextContextMenuItem(ID_SELECT_ALL);
}
break;
+ case KeyEvent.KEYCODE_Z:
+ if (canUndo()) {
+ return onTextContextMenuItem(ID_UNDO);
+ }
+ break;
case KeyEvent.KEYCODE_X:
if (canCut()) {
return onTextContextMenuItem(ID_CUT);
@@ -8394,6 +8404,15 @@
}
break;
}
+ } else if (event.hasModifiers(KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON)) {
+ // Handle Ctrl-Shift shortcuts.
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_Z:
+ if (canRedo()) {
+ return onTextContextMenuItem(ID_REDO);
+ }
+ break;
+ }
}
return super.onKeyShortcut(keyCode, event);
}
@@ -8770,6 +8789,8 @@
}
static final int ID_SELECT_ALL = android.R.id.selectAll;
+ static final int ID_UNDO = android.R.id.undo;
+ static final int ID_REDO = android.R.id.redo;
static final int ID_CUT = android.R.id.cut;
static final int ID_COPY = android.R.id.copy;
static final int ID_PASTE = android.R.id.paste;
@@ -8800,6 +8821,18 @@
selectAllText();
return true;
+ case ID_UNDO:
+ if (mEditor != null) {
+ mEditor.undo();
+ }
+ return true; // Returns true even if nothing was undone.
+
+ case ID_REDO:
+ if (mEditor != null) {
+ mEditor.redo();
+ }
+ return true; // Returns true even if nothing was undone.
+
case ID_PASTE:
paste(min, max);
return true;
@@ -8929,7 +8962,17 @@
* @hide
*/
protected void stopSelectionActionMode() {
- mEditor.stopSelectionActionMode();
+ if (mEditor != null) {
+ mEditor.stopSelectionActionMode();
+ }
+ }
+
+ boolean canUndo() {
+ return mEditor != null && mEditor.canUndo();
+ }
+
+ boolean canRedo() {
+ return mEditor != null && mEditor.canRedo();
}
boolean canCut() {
@@ -9299,6 +9342,7 @@
CharSequence text;
boolean frozenWithFocus;
CharSequence error;
+ ParcelableParcel editorState; // Optional state from Editor.
SavedState(Parcelable superState) {
super(superState);
@@ -9318,6 +9362,13 @@
out.writeInt(1);
TextUtils.writeToParcel(error, out, flags);
}
+
+ if (editorState == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ editorState.writeToParcel(out, flags);
+ }
}
@Override
@@ -9353,6 +9404,10 @@
if (in.readInt() != 0) {
error = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
}
+
+ if (in.readInt() != 0) {
+ editorState = ParcelableParcel.CREATOR.createFromParcel(in);
+ }
}
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index be4cdc1..207f675 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -17,6 +17,7 @@
package android.widget;
import android.annotation.IntDef;
+import android.annotation.StringRes;
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.content.Context;
@@ -280,7 +281,7 @@
*
* @throws Resources.NotFoundException if the resource can't be found.
*/
- public static Toast makeText(Context context, int resId, @Duration int duration)
+ public static Toast makeText(Context context, @StringRes int resId, @Duration int duration)
throws Resources.NotFoundException {
return makeText(context, context.getResources().getText(resId), duration);
}
@@ -289,7 +290,7 @@
* Update the text in a Toast that was previously created using one of the makeText() methods.
* @param resId The new text for the Toast.
*/
- public void setText(int resId) {
+ public void setText(@StringRes int resId) {
setText(mContext.getText(resId));
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 183527cb..9ae9fa7 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -35,6 +35,8 @@
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.TextServicesManager;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -518,7 +520,8 @@
return NOT_A_SUBTYPE_ID;
}
- private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
+ @VisibleForTesting
+ public static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
Resources res, InputMethodInfo imi) {
final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi);
final String systemLocale = res.getConfiguration().locale.toString();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 20bb95e..d0c7f8c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -94,7 +94,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 116 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 118 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -208,7 +208,7 @@
final HistoryItem mHistoryLastLastWritten = new HistoryItem();
final HistoryItem mHistoryReadTmp = new HistoryItem();
final HistoryItem mHistoryAddTmp = new HistoryItem();
- final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<HistoryTag, Integer>();
+ final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap();
String[] mReadHistoryStrings;
int[] mReadHistoryUids;
int mReadHistoryChars;
@@ -227,6 +227,38 @@
HistoryItem mHistoryLastEnd;
HistoryItem mHistoryCache;
+ // Used by computeHistoryStepDetails
+ HistoryStepDetails mLastHistoryStepDetails = null;
+ byte mLastHistoryStepLevel = 0;
+ final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
+ final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
+ final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
+ /**
+ * Total time (in 1/100 sec) spent executing in user code.
+ */
+ long mLastStepCpuUserTime;
+ long mCurStepCpuUserTime;
+ /**
+ * Total time (in 1/100 sec) spent executing in kernel code.
+ */
+ long mLastStepCpuSystemTime;
+ long mCurStepCpuSystemTime;
+ /**
+ * Times from /proc/stat
+ */
+ long mLastStepStatUserTime;
+ long mLastStepStatSystemTime;
+ long mLastStepStatIOWaitTime;
+ long mLastStepStatIrqTime;
+ long mLastStepStatSoftIrqTime;
+ long mLastStepStatIdleTime;
+ long mCurStepStatUserTime;
+ long mCurStepStatSystemTime;
+ long mCurStepStatIOWaitTime;
+ long mCurStepStatIrqTime;
+ long mCurStepStatSoftIrqTime;
+ long mCurStepStatIdleTime;
+
private HistoryItem mHistoryIterator;
private boolean mReadOverflow;
private boolean mIteratingHistory;
@@ -1938,6 +1970,10 @@
static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
static final int STATE_BATTERY_PLUG_SHIFT = 24;
+ // We use the low bit of the battery state int to indicate that we have full details
+ // from a battery level change.
+ static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
+
public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
dest.writeInt(DELTA_TIME_ABS);
@@ -1958,7 +1994,11 @@
deltaTimeToken = (int)deltaTime;
}
int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
- final int batteryLevelInt = buildBatteryLevelInt(cur);
+ final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
+ ? BATTERY_DELTA_LEVEL_FLAG : 0;
+ final boolean computeStepDetails = includeStepDetails != 0
+ || mLastHistoryStepDetails == null;
+ final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
if (batteryLevelIntChanged) {
firstToken |= DELTA_BATTERY_LEVEL_FLAG;
@@ -2040,12 +2080,26 @@
+ cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
+ cur.eventTag.string);
}
+ if (computeStepDetails) {
+ computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
+ if (includeStepDetails != 0) {
+ mCurHistoryStepDetails.writeToParcel(dest);
+ }
+ cur.stepDetails = mCurHistoryStepDetails;
+ mLastHistoryStepDetails = mCurHistoryStepDetails;
+ } else {
+ cur.stepDetails = null;
+ }
+ if (mLastHistoryStepLevel < cur.batteryLevel) {
+ mLastHistoryStepDetails = null;
+ }
+ mLastHistoryStepLevel = cur.batteryLevel;
}
private int buildBatteryLevelInt(HistoryItem h) {
return ((((int)h.batteryLevel)<<25)&0xfe000000)
- | ((((int)h.batteryTemperature)<<14)&0x01ffc000)
- | (((int)h.batteryVoltage)&0x00003fff);
+ | ((((int)h.batteryTemperature)<<14)&0x01ff8000)
+ | ((((int)h.batteryVoltage)<<1)&0x00007fff);
}
private int buildStateInt(HistoryItem h) {
@@ -2063,6 +2117,98 @@
| (h.states&(~DELTA_STATE_MASK));
}
+ private void computeHistoryStepDetails(final HistoryStepDetails out,
+ final HistoryStepDetails last) {
+ final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
+
+ // Perform a CPU update right after we do this collection, so we have started
+ // collecting good data for the next step.
+ requestImmediateCpuUpdate();
+
+ if (last == null) {
+ // We are not generating a delta, so all we need to do is reset the stats
+ // we will later be doing a delta from.
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ uid.mLastStepUserTime = uid.mCurStepUserTime;
+ uid.mLastStepSystemTime = uid.mCurStepSystemTime;
+ }
+ mLastStepCpuUserTime = mCurStepCpuUserTime;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime;
+ mLastStepStatUserTime = mCurStepStatUserTime;
+ mLastStepStatSystemTime = mCurStepStatSystemTime;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
+ mLastStepStatIrqTime = mCurStepStatIrqTime;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
+ mLastStepStatIdleTime = mCurStepStatIdleTime;
+ tmp.clear();
+ return;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
+ + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
+ + " irq=" + mLastStepStatIrqTime + " sirq="
+ + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
+ Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
+ + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
+ + " irq=" + mCurStepStatIrqTime + " sirq="
+ + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
+ }
+ out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
+ out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
+ out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
+ out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
+ out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
+ out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
+ out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
+ out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
+ out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
+ out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
+ out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
+ final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
+ final int totalTime = totalUTime + totalSTime;
+ uid.mLastStepUserTime = uid.mCurStepUserTime;
+ uid.mLastStepSystemTime = uid.mCurStepSystemTime;
+ if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
+ continue;
+ }
+ if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
+ out.appCpuUid3 = uid.mUid;
+ out.appCpuUTime3 = totalUTime;
+ out.appCpuSTime3 = totalSTime;
+ } else {
+ out.appCpuUid3 = out.appCpuUid2;
+ out.appCpuUTime3 = out.appCpuUTime2;
+ out.appCpuSTime3 = out.appCpuSTime2;
+ if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
+ out.appCpuUid2 = uid.mUid;
+ out.appCpuUTime2 = totalUTime;
+ out.appCpuSTime2 = totalSTime;
+ } else {
+ out.appCpuUid2 = out.appCpuUid1;
+ out.appCpuUTime2 = out.appCpuUTime1;
+ out.appCpuSTime2 = out.appCpuSTime1;
+ out.appCpuUid1 = uid.mUid;
+ out.appCpuUTime1 = totalUTime;
+ out.appCpuSTime1 = totalSTime;
+ }
+ }
+ }
+ mLastStepCpuUserTime = mCurStepCpuUserTime;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime;
+ mLastStepStatUserTime = mCurStepStatUserTime;
+ mLastStepStatSystemTime = mCurStepStatSystemTime;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
+ mLastStepStatIrqTime = mCurStepStatIrqTime;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
+ mLastStepStatIdleTime = mCurStepStatIdleTime;
+ }
+
public void readHistoryDelta(Parcel src, HistoryItem cur) {
int firstToken = src.readInt();
int deltaTimeToken = firstToken&DELTA_TIME_MASK;
@@ -2091,8 +2237,9 @@
cur.numReadInts += 2;
}
+ final int batteryLevelInt;
if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
- int batteryLevelInt = src.readInt();
+ batteryLevelInt = src.readInt();
cur.batteryLevel = (byte)((batteryLevelInt>>25)&0x7f);
cur.batteryTemperature = (short)((batteryLevelInt<<7)>>21);
cur.batteryVoltage = (char)(batteryLevelInt&0x3fff);
@@ -2102,6 +2249,8 @@
+ " batteryLevel=" + cur.batteryLevel
+ " batteryTemp=" + cur.batteryTemperature
+ " batteryVolt=" + (int)cur.batteryVoltage);
+ } else {
+ batteryLevelInt = 0;
}
if ((firstToken&DELTA_STATE_FLAG) != 0) {
@@ -2180,6 +2329,13 @@
} else {
cur.eventCode = HistoryItem.EVENT_NONE;
}
+
+ if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
+ cur.stepDetails = mReadHistoryStepDetails;
+ cur.stepDetails.readFromParcel(src);
+ } else {
+ cur.stepDetails = null;
+ }
}
@Override
@@ -2207,6 +2363,7 @@
&& (diffStates2&lastDiffStates2) == 0
&& (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
&& (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
+ && mHistoryLastWritten.stepDetails == null
&& (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
|| cur.eventCode == HistoryItem.EVENT_NONE)
&& mHistoryLastWritten.batteryLevel == cur.batteryLevel
@@ -2632,6 +2789,11 @@
}
}
+ private void requestImmediateCpuUpdate() {
+ mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
+ }
+
public void setRecordAllHistoryLocked(boolean enabled) {
mRecordAllHistory = enabled;
if (!enabled) {
@@ -2823,6 +2985,10 @@
public int startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ if (!mOnBatteryInternal) {
+ return -1;
+ }
+
final int N = mPartialTimers.size();
if (N == 0) {
mLastPartialTimers.clear();
@@ -2853,7 +3019,23 @@
return 0;
}
- public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
+ public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime,
+ int totalUTime, int totalSTime, int statUserTime, int statSystemTime,
+ int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime,
+ long[] cpuSpeedTimes) {
+ if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
+ + " user=" + statUserTime + " sys=" + statSystemTime
+ + " io=" + statIOWaitTime + " irq=" + statIrqTime
+ + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
+ mCurStepCpuUserTime += totalUTime;
+ mCurStepCpuSystemTime += totalSTime;
+ mCurStepStatUserTime += statUserTime;
+ mCurStepStatSystemTime += statSystemTime;
+ mCurStepStatIOWaitTime += statIOWaitTime;
+ mCurStepStatIrqTime += statIrqTime;
+ mCurStepStatSoftIrqTime += statSoftIrqTime;
+ mCurStepStatIdleTime += statIdleTime;
+
final int N = mPartialTimers.size();
if (perc != 0) {
int num = 0;
@@ -2874,26 +3056,24 @@
if (st.mInList) {
Uid uid = st.mUid;
if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- int myUTime = utime/num;
- int mySTime = stime/num;
- utime -= myUTime;
- stime -= mySTime;
+ int myUTime = remainUTime/num;
+ int mySTime = remainSTtime/num;
+ remainUTime -= myUTime;
+ remainSTtime -= mySTime;
num--;
Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
- proc.addCpuTimeLocked(myUTime, mySTime);
- proc.addSpeedStepTimes(cpuSpeedTimes);
+ proc.addCpuTimeLocked(myUTime, mySTime, cpuSpeedTimes);
}
}
}
}
// Just in case, collect any lost CPU time.
- if (utime != 0 || stime != 0) {
+ if (remainUTime != 0 || remainSTtime != 0) {
Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
if (uid != null) {
Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
- proc.addCpuTimeLocked(utime, stime);
- proc.addSpeedStepTimes(cpuSpeedTimes);
+ proc.addCpuTimeLocked(remainUTime, remainSTtime, cpuSpeedTimes);
}
}
}
@@ -4214,6 +4394,14 @@
LongSamplingCounter mMobileRadioActiveCount;
/**
+ * The CPU times we had at the last history details update.
+ */
+ long mLastStepUserTime;
+ long mLastStepSystemTime;
+ long mCurStepUserTime;
+ long mCurStepSystemTime;
+
+ /**
* The statistics we have collected for this uid's wake locks.
*/
final OverflowArrayMap<Wakelock> mWakelockStats = new OverflowArrayMap<Wakelock>() {
@@ -4876,6 +5064,9 @@
mPackageStats.clear();
}
+ mLastStepUserTime = mLastStepSystemTime = 0;
+ mCurStepUserTime = mCurStepSystemTime = 0;
+
if (!active) {
if (mWifiRunningTimer != null) {
mWifiRunningTimer.detach();
@@ -5678,9 +5869,22 @@
return BatteryStatsImpl.this;
}
- public void addCpuTimeLocked(int utime, int stime) {
+ public void addCpuTimeLocked(int utime, int stime, long[] speedStepBins) {
mUserTime += utime;
+ mCurStepUserTime += utime;
mSystemTime += stime;
+ mCurStepSystemTime += stime;
+
+ for (int i = 0; i < mSpeedBins.length && i < speedStepBins.length; i++) {
+ long amt = speedStepBins[i];
+ if (amt != 0) {
+ SamplingCounter c = mSpeedBins[i];
+ if (c == null) {
+ mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
+ }
+ c.addCountAtomic(speedStepBins[i]);
+ }
+ }
}
public void addForegroundTimeLocked(long ttime) {
@@ -5770,20 +5974,6 @@
return val;
}
- /* Called by ActivityManagerService when CPU times are updated. */
- public void addSpeedStepTimes(long[] values) {
- for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
- long amt = values[i];
- if (amt != 0) {
- SamplingCounter c = mSpeedBins[i];
- if (c == null) {
- mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
- }
- c.addCountAtomic(values[i]);
- }
- }
- }
-
@Override
public long getTimeAtCpuSpeedStep(int speedStep, int which) {
if (speedStep < mSpeedBins.length) {
@@ -6756,6 +6946,18 @@
mWakeupReasonStats.clear();
}
+ mLastHistoryStepDetails = null;
+ mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
+ mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
+ mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
+ mLastStepStatUserTime = mCurStepStatUserTime = 0;
+ mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
+ mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
+ mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
+
initDischarge();
clearHistoryLocked();
@@ -6872,7 +7074,7 @@
reset = true;
mNumDischargeStepDurations = 0;
}
- mOnBattery = mOnBatteryInternal = onBattery;
+ mOnBattery = mOnBatteryInternal = true;
mLastDischargeStepLevel = level;
mMinDischargeStepLevel = level;
mLastDischargeStepTime = -1;
@@ -6900,7 +7102,7 @@
mDischargeAmountScreenOff = 0;
updateTimeBasesLocked(true, !screenOn, uptime, realtime);
} else {
- mOnBattery = mOnBatteryInternal = onBattery;
+ mOnBattery = mOnBatteryInternal = false;
pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index b5338df..501e0ec 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -152,6 +152,7 @@
private int mRelIrqTime;
private int mRelSoftIrqTime;
private int mRelIdleTime;
+ private boolean mRelStatsAreGood;
private int[] mCurPids;
private int[] mCurThreadPids;
@@ -285,10 +286,9 @@
public void update() {
if (DEBUG) Slog.v(TAG, "Update: " + this);
- mLastSampleTime = mCurrentSampleTime;
- mCurrentSampleTime = SystemClock.uptimeMillis();
- mLastSampleRealTime = mCurrentSampleRealTime;
- mCurrentSampleRealTime = SystemClock.elapsedRealtime();
+
+ final long nowUptime = SystemClock.uptimeMillis();
+ final long nowRealtime = SystemClock.elapsedRealtime();
final long[] sysCpu = mSystemCpuData;
if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,
@@ -304,30 +304,53 @@
final long irqtime = sysCpu[5];
final long softirqtime = sysCpu[6];
- mRelUserTime = (int)(usertime - mBaseUserTime);
- mRelSystemTime = (int)(systemtime - mBaseSystemTime);
- mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
- mRelIrqTime = (int)(irqtime - mBaseIrqTime);
- mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
- mRelIdleTime = (int)(idletime - mBaseIdleTime);
+ // This code is trying to avoid issues with idle time going backwards,
+ // but currently it gets into situations where it triggers most of the time. :(
+ if (true || (usertime >= mBaseUserTime && systemtime >= mBaseSystemTime
+ && iowaittime >= mBaseIoWaitTime && irqtime >= mBaseIrqTime
+ && softirqtime >= mBaseSoftIrqTime && idletime >= mBaseIdleTime)) {
+ mRelUserTime = (int)(usertime - mBaseUserTime);
+ mRelSystemTime = (int)(systemtime - mBaseSystemTime);
+ mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
+ mRelIrqTime = (int)(irqtime - mBaseIrqTime);
+ mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
+ mRelIdleTime = (int)(idletime - mBaseIdleTime);
+ mRelStatsAreGood = true;
- if (DEBUG) {
- Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
- + " S:" + sysCpu[2] + " I:" + sysCpu[3]
- + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
- + " O:" + sysCpu[6]);
- Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
- + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
+ if (DEBUG) {
+ Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
+ + " S:" + sysCpu[2] + " I:" + sysCpu[3]
+ + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
+ + " O:" + sysCpu[6]);
+ Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
+ + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
+ }
+
+ mBaseUserTime = usertime;
+ mBaseSystemTime = systemtime;
+ mBaseIoWaitTime = iowaittime;
+ mBaseIrqTime = irqtime;
+ mBaseSoftIrqTime = softirqtime;
+ mBaseIdleTime = idletime;
+
+ } else {
+ mRelUserTime = 0;
+ mRelSystemTime = 0;
+ mRelIoWaitTime = 0;
+ mRelIrqTime = 0;
+ mRelSoftIrqTime = 0;
+ mRelIdleTime = 0;
+ mRelStatsAreGood = false;
+ Slog.w(TAG, "/proc/stats has gone backwards; skipping CPU update");
+ return;
}
-
- mBaseUserTime = usertime;
- mBaseSystemTime = systemtime;
- mBaseIoWaitTime = iowaittime;
- mBaseIrqTime = irqtime;
- mBaseSoftIrqTime = softirqtime;
- mBaseIdleTime = idletime;
}
+ mLastSampleTime = mCurrentSampleTime;
+ mCurrentSampleTime = nowUptime;
+ mLastSampleRealTime = mCurrentSampleRealTime;
+ mCurrentSampleRealTime = nowRealtime;
+
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
try {
mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats);
@@ -647,6 +670,10 @@
return mRelIdleTime;
}
+ final public boolean hasGoodLastStats() {
+ return mRelStatsAreGood;
+ }
+
final public float getTotalCpuPercent() {
int denom = mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime;
if (denom <= 0) {
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index c9b44be..a55fe9a 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -399,7 +399,7 @@
throws IllegalArgumentException {
int curArg = 0;
- boolean seenRuntimeArgs = true;
+ boolean seenRuntimeArgs = false;
for ( /* curArg */ ; curArg < args.length; curArg++) {
String arg = args[curArg];
@@ -533,14 +533,18 @@
}
}
- if (!seenRuntimeArgs) {
- throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
+ if (abiListQuery) {
+ if (args.length - curArg > 0) {
+ throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
+ }
+ } else {
+ if (!seenRuntimeArgs) {
+ throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
+ }
+
+ remainingArgs = new String[args.length - curArg];
+ System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length);
}
-
- remainingArgs = new String[args.length - curArg];
-
- System.arraycopy(args, curArg, remainingArgs, 0,
- remainingArgs.length);
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 035b017..400ea37 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -504,8 +504,8 @@
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
- "--runtime-init",
"--nice-name=system_server",
+ "--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
diff --git a/core/java/com/android/internal/view/ActionModeWrapper.java b/core/java/com/android/internal/view/ActionModeWrapper.java
new file mode 100644
index 0000000..ef1981a
--- /dev/null
+++ b/core/java/com/android/internal/view/ActionModeWrapper.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.content.Context;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.widget.ActionBarContextView;
+
+/**
+ * ActionMode implementation that wraps several actions modes and creates them on the fly depending
+ * on the ActionMode type chosen by the client.
+ */
+public class ActionModeWrapper extends ActionMode {
+
+ private ActionMode mActionMode;
+ private final Context mContext;
+ private MenuBuilder mMenu;
+ private final ActionMode.Callback mCallback;
+ private boolean mTypeLocked = false;
+
+ private CharSequence mTitle;
+ private CharSequence mSubtitle;
+ private View mCustomView;
+
+ // Fields for StandaloneActionMode
+ private ActionBarContextView mActionModeView;
+ private boolean mIsFocusable;
+
+ public ActionModeWrapper(Context context, ActionMode.Callback callback) {
+ mContext = context;
+ mMenu = new MenuBuilder(context).setDefaultShowAsAction(
+ MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ mCallback = callback;
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ if (mActionMode != null) {
+ mActionMode.setTitle(title);
+ } else {
+ mTitle = title;
+ }
+ }
+
+ @Override
+ public void setTitle(int resId) {
+ if (mActionMode != null) {
+ mActionMode.setTitle(resId);
+ } else {
+ mTitle = resId != 0 ? mContext.getString(resId) : null;
+ }
+ }
+
+ @Override
+ public void setSubtitle(CharSequence subtitle) {
+ if (mActionMode != null) {
+ mActionMode.setSubtitle(subtitle);
+ } else {
+ mSubtitle = subtitle;
+ }
+ }
+
+ @Override
+ public void setSubtitle(int resId) {
+ if (mActionMode != null) {
+ mActionMode.setSubtitle(resId);
+ } else {
+ mSubtitle = resId != 0 ? mContext.getString(resId) : null;
+ }
+ }
+
+ @Override
+ public void setCustomView(View view) {
+ if (mActionMode != null) {
+ mActionMode.setCustomView(view);
+ } else {
+ mCustomView = view;
+ }
+ }
+
+ /**
+ * Set the current type as final and create the necessary ActionMode. After this call, any
+ * changes to the ActionMode type will be ignored.
+ */
+ public void lockType() {
+ mTypeLocked = true;
+ switch (getType()) {
+ case ActionMode.TYPE_PRIMARY:
+ default:
+ mActionMode = new StandaloneActionMode(
+ mActionModeView.getContext(),
+ mActionModeView, mCallback, mIsFocusable, mMenu);
+ break;
+ case ActionMode.TYPE_FLOATING:
+ // Not implemented yet.
+ break;
+ }
+
+ if (mActionMode == null) {
+ return;
+ }
+
+ mActionMode.setTitle(mTitle);
+ mActionMode.setSubtitle(mSubtitle);
+ if (mCustomView != null) {
+ mActionMode.setCustomView(mCustomView);
+ }
+
+ mTitle = null;
+ mSubtitle = null;
+ mCustomView = null;
+ }
+
+ @Override
+ public void setType(int type) {
+ if (!mTypeLocked) {
+ super.setType(type);
+ } else {
+ throw new IllegalStateException(
+ "You can't change the ActionMode's type after onCreateActionMode.");
+ }
+ }
+
+ @Override
+ public void invalidate() {
+ if (mActionMode != null) {
+ mActionMode.invalidate();
+ }
+ }
+
+ @Override
+ public void finish() {
+ if (mActionMode != null) {
+ mActionMode.finish();
+ }
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mMenu;
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ if (mActionMode != null) {
+ return mActionMode.getTitle();
+ }
+ return mTitle;
+ }
+
+ @Override
+ public CharSequence getSubtitle() {
+ if (mActionMode != null) {
+ return mActionMode.getSubtitle();
+ }
+ return mSubtitle;
+ }
+
+ @Override
+ public View getCustomView() {
+ if (mActionMode != null) {
+ return mActionMode.getCustomView();
+ }
+ return mCustomView;
+ }
+
+ @Override
+ public MenuInflater getMenuInflater() {
+ return new MenuInflater(mContext);
+ }
+
+ public void setActionModeView(ActionBarContextView actionModeView) {
+ mActionModeView = actionModeView;
+ }
+
+ public void setFocusable(boolean focusable) {
+ mIsFocusable = focusable;
+ }
+
+}
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index d5d3602..2812b77 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -20,6 +20,7 @@
import com.android.internal.view.menu.SubMenuBuilder;
import com.android.internal.widget.ActionBarContextView;
+import android.annotation.Nullable;
import android.content.Context;
import android.view.ActionMode;
import android.view.Menu;
@@ -41,13 +42,15 @@
private MenuBuilder mMenu;
public StandaloneActionMode(Context context, ActionBarContextView view,
- ActionMode.Callback callback, boolean isFocusable) {
+ ActionMode.Callback callback, boolean isFocusable, @Nullable MenuBuilder menuBuilder) {
mContext = context;
mContextView = view;
mCallback = callback;
- mMenu = new MenuBuilder(view.getContext()).setDefaultShowAsAction(
- MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ mMenu = (menuBuilder != null)
+ ? menuBuilder
+ : new MenuBuilder(view.getContext()).setDefaultShowAsAction(
+ MenuItem.SHOW_AS_ACTION_IF_ROOM);
mMenu.setCallback(this);
mFocusable = isFocusable;
}
@@ -64,12 +67,12 @@
@Override
public void setTitle(int resId) {
- setTitle(mContext.getString(resId));
+ setTitle(resId != 0 ? mContext.getString(resId) : null);
}
@Override
public void setSubtitle(int resId) {
- setSubtitle(mContext.getString(resId));
+ setSubtitle(resId != 0 ? mContext.getString(resId) : null);
}
@Override
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 5d3f464..ae5999a 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -158,7 +158,7 @@
removeView(mCustomView);
}
mCustomView = view;
- if (mTitleLayout != null) {
+ if (view != null && mTitleLayout != null) {
removeView(mTitleLayout);
mTitleLayout = null;
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 7f6c50f..bfa0534 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -49,6 +49,7 @@
#include <AnimationContext.h>
#include <DisplayListRenderer.h>
+#include <FrameInfo.h>
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>
@@ -394,7 +395,7 @@
proxy->initialize(surface);
// Shadows can't be used via this interface, so just set the light source
// to all 0s. (and width & height are unused, TODO remove them)
- proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0);
+ proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0, 1.0f);
return (jlong) proxy;
}
@@ -406,8 +407,11 @@
static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
- nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
- proxy->syncAndDrawFrame(frameTimeNs, 0, 1.0f);
+ nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ UiFrameInfoBuilder(proxy->frameInfo())
+ .setVsync(vsync, vsync)
+ .addFlag(FrameInfoFlags::kSurfaceCanvas);
+ proxy->syncAndDrawFrame();
}
static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 068b24e..ad93301 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -281,10 +281,10 @@
static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
jint width, jint height,
jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius,
- jint ambientShadowAlpha, jint spotShadowAlpha) {
+ jint ambientShadowAlpha, jint spotShadowAlpha, jfloat density) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
- ambientShadowAlpha, spotShadowAlpha);
+ ambientShadowAlpha, spotShadowAlpha, density);
}
static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -294,9 +294,13 @@
}
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density) {
+ jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
+ LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
+ "Mismatched size expectations, given %d expected %d",
+ frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
+ env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
+ return proxy->syncAndDrawFrame();
}
static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
@@ -391,10 +395,10 @@
}
static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject javaFileDescriptor) {
+ jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
- proxy->dumpProfileInfo(fd);
+ proxy->dumpProfileInfo(fd, dumpFlags);
}
// ----------------------------------------------------------------------------
@@ -425,9 +429,9 @@
{ "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
{ "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
{ "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
- { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
+ { "nSetup", "(JIIFFFFIIF)V", (void*) android_view_ThreadedRenderer_setup },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
- { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+ { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
{ "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
@@ -442,7 +446,7 @@
{ "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
{ "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
{ "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
- { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
+ { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
{ "setupShadersDiskCache", "(Ljava/lang/String;)V",
(void*) android_view_ThreadedRenderer_setupShadersDiskCache },
};
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 8165ab6..f1b4b13 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1777,8 +1777,8 @@
<string name="item_is_selected" msgid="949687401682476608">"არჩეულია <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="7570091317001980053">"მიმაგრების გასაუქმებლად ერთდროულად შეეხეთ და არ აუშვათ ღილაკებს „უკან“ და „გადახედვა“."</string>
- <string name="lock_to_app_toast_accessible" msgid="8239120109365070664">"ამ ეკრანისთვის მიმაგრების გასაუქმებლად შეეხეთ და არ აუშვათ ღილაკებს „გადახედვა“."</string>
+ <string name="lock_to_app_toast" msgid="7570091317001980053">"მიმაგრების გასაუქმებლად ერთდროულად შეეხეთ და არ აუშვათ ღილაკებს „უკან“ და „მიმოხილვა“."</string>
+ <string name="lock_to_app_toast_accessible" msgid="8239120109365070664">"ამ ეკრანისთვის მიმაგრების გასაუქმებლად, შეეხეთ და არ აუშვათ „მიმოხილვა“-ს."</string>
<string name="lock_to_app_toast_locked" msgid="8739004135132606329">"ეკრანი დაფიქსირებული. ფიქსაციის მოხსნა თქვენო ორგანიზაციის მიერ ნებადართული არ არის."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ეკრანი დაფიქსირდა"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"ეკრანს ფიქსაცია მოეხსნა"</string>
diff --git a/core/res/res/values-mcc259-mnc05/config.xml b/core/res/res/values-mcc259-mnc05/config.xml
new file mode 100644
index 0000000..065668c
--- /dev/null
+++ b/core/res/res/values-mcc259-mnc05/config.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- The list of ril radio technologies (see ServiceState.java) which only support
+ a single data connection at one time. This may change by carrier via
+ overlays (some don't support multiple pdp on UMTS). All unlisted radio
+ tech types support unlimited types (practically only 2-4 used). -->
+ <integer-array name="config_onlySingleDcAllowed">
+ <item>1</item> <!-- GPRS -->
+ <item>2</item> <!-- EDGE -->
+ <item>3</item> <!-- UMTS -->
+ <item>9</item> <!-- HSDPA -->
+ <item>10</item> <!-- HSUPA -->
+ <item>11</item> <!-- HSPA -->
+ <item>14</item> <!-- LTE -->
+ <item>15</item> <!-- HSPAP -->
+ </integer-array>
+</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c9aa316..0fe8006 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -200,7 +200,7 @@
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçak modu AÇIK"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Uçak modu KAPALI"</string>
<string name="global_action_settings" msgid="1756531602592545966">"Ayarlar"</string>
- <string name="global_action_voice_assist" msgid="7751191495200504480">"Ses Yardımı"</string>
+ <string name="global_action_voice_assist" msgid="7751191495200504480">"Sesli Yardım"</string>
<string name="global_action_lockdown" msgid="8751542514724332873">"Şimdi kilitle"</string>
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 307a1ea..745aa73 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -43,4 +43,12 @@
<!-- Flags enabling default window features. See Window.java -->
<bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
<bool name="config_defaultWindowFeatureContextMenu">false</bool>
+
+ <!-- Time adjustment, in milliseconds, applied to the default double tap threshold
+ used for gesture detection by the screen magnifier. -->
+ <integer name="config_screen_magnification_multi_tap_adjustment">25</integer>
+
+ <!-- Scale factor threshold used by the screen magnifier to determine when to switch from
+ panning to scaling the magnification viewport. -->
+ <item name="config_screen_magnification_scaling_threshold" format="float" type="dimen">0.1</item>
</resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 80fad63..93f58cba 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -25,6 +25,7 @@
<color name="primary_material_light">#ffefefef</color>
<color name="primary_dark_material_dark">#ff000000</color>
<color name="primary_dark_material_light">#ff757575</color>
+ <color name="primary_dark_material_light_light_status_bar">#ffe0e0e0</color>
<!-- 26% white (foreground) -->
<color name="ripple_material_dark">#42ffffff</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2041777..51c6a66 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2060,4 +2060,12 @@
<!-- Whether to start in touch mode -->
<bool name="config_defaultInTouchMode">true</bool>
+
+ <!-- Time adjustment, in milliseconds, applied to the default double tap threshold
+ used for gesture detection by the screen magnifier. -->
+ <integer name="config_screen_magnification_multi_tap_adjustment">-50</integer>
+
+ <!-- Scale factor threshold used by the screen magnifier to determine when to switch from
+ panning to scaling the magnification viewport. -->
+ <item name="config_screen_magnification_scaling_threshold" format="float" type="dimen">0.3</item>
</resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bd24f3e..1f4d37c 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -89,4 +89,6 @@
<item type="id" name="parentMatrix" />
<item type="id" name="statusBarBackground" />
<item type="id" name="navigationBarBackground" />
+ <item type="id" name="undo" />
+ <item type="id" name="redo" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3ac7374..8814138 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2632,5 +2632,11 @@
<public type="style" name="Theme.Material.DayNight.NoActionBar.Overscan" />
<public type="style" name="Theme.Material.DayNight.NoActionBar.TranslucentDecor" />
<public type="style" name="Theme.Material.DayNight.Panel" />
+ <public type="style" name="Theme.Material.Light.LightStatusBar" />
+
+ <!-- Context menu ID for the "Undo" menu item to undo the last text edit operation. -->
+ <public type="id" name="undo" />
+ <!-- Context menu ID for the "Redo" menu item to redo the last text edit operation. -->
+ <public type="id" name="redo" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c43977da..b414634 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2157,4 +2157,7 @@
<java-symbol type="xml" name="bookmarks" />
<java-symbol type="integer" name="config_defaultNightMode" />
+
+ <java-symbol type="integer" name="config_screen_magnification_multi_tap_adjustment" />
+ <java-symbol type="dimen" name="config_screen_magnification_scaling_threshold" />
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 701afee..0107356 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -754,6 +754,13 @@
<item name="colorPrimary">@color/primary_material_dark</item>
</style>
+ <!-- Variant of the material (light) theme that has a light status bar background with dark
+ status bar contents. -->
+ <style name="Theme.Material.Light.LightStatusBar">
+ <item name="colorPrimaryDark">@color/primary_dark_material_light_light_status_bar</item>
+ <item name="windowHasLightStatusBar">true</item>
+ </style>
+
<style name="ThemeOverlay" />
<style name="ThemeOverlay.Material" />
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
index 1557918..86021e5 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -29,8 +29,6 @@
import com.android.internal.inputmethod.InputMethodUtils;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -38,19 +36,33 @@
public class InputMethodTest extends InstrumentationTestCase {
private static final boolean IS_AUX = true;
private static final boolean IS_DEFAULT = true;
- private static final boolean IS_AUTO = true;
+ private static final boolean IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE = true;
private static final boolean IS_ASCII_CAPABLE = true;
+ private static final boolean IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = true;
private static final boolean IS_SYSTEM_READY = true;
- private static final ArrayList<InputMethodSubtype> NO_SUBTYPE = null;
+ private static final Locale LOCALE_EN = new Locale("en");
private static final Locale LOCALE_EN_US = new Locale("en", "US");
private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
private static final Locale LOCALE_EN_IN = new Locale("en", "IN");
+ private static final Locale LOCALE_FI = new Locale("fi");
+ private static final Locale LOCALE_FI_FI = new Locale("fi", "FI");
+ private static final Locale LOCALE_FIL = new Locale("fil");
+ private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH");
+ private static final Locale LOCALE_FR = new Locale("fr");
+ private static final Locale LOCALE_FR_CA = new Locale("fr", "CA");
private static final Locale LOCALE_HI = new Locale("hi");
private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN");
private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW");
+ private static final Locale LOCALE_IN = new Locale("in");
+ private static final Locale LOCALE_ID = new Locale("id");
private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
private static final String SUBTYPE_MODE_VOICE = "voice";
+ private static final String SUBTYPE_MODE_ANY = null;
+ private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
+ private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
+ private static final String EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE =
+ "EnabledWhenDefaultIsNotAsciiCapable";
@SmallTest
public void testVoiceImes() throws Exception {
@@ -159,10 +171,417 @@
}
}
+ @SmallTest
+ public void testGetImplicitlyApplicableSubtypesLocked() throws Exception {
+ final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
+ createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 =
+ createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+
+ // Make sure that an automatic subtype (overridesImplicitlyEnabledSubtype:true) is
+ // selected no matter what locale is specified.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoEnGB);
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(autoSubtype); // overridesImplicitlyEnabledSubtype == true
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
+ assertEquals(1, result.size());
+ verifyEquality(autoSubtype, result.get(0));
+ }
+
+ // Make sure that a subtype whose locale is exactly equal to the specified locale is
+ // selected as long as there is no no automatic subtype
+ // (overridesImplicitlyEnabledSubtype:true) in the given list.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS); // locale == "en_US"
+ subtypes.add(nonAutoEnGB);
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnUS, result.get(0));
+ }
+
+ // Make sure that a subtype whose locale is exactly equal to the specified locale is
+ // selected as long as there is no automatic subtype
+ // (overridesImplicitlyEnabledSubtype:true) in the given list.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoEnGB); // locale == "en_GB"
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_GB, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnGB, result.get(0));
+ }
+
+ // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and
+ // any subtype whose locale is exactly equal to the specified locale in the given list,
+ // try to find a subtype whose language is equal to the language part of the given locale.
+ // Here make sure that a subtype (locale: "fr_CA") can be found with locale: "fr".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFrCA); // locale == "fr_CA"
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoFrCA, result.get(0));
+ }
+ // Then make sure that a subtype (locale: "fr") can be found with locale: "fr_CA".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFr); // locale == "fr"
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR_CA, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoFrCA, result.get(0));
+ }
+
+ // Make sure that subtypes which have "EnabledWhenDefaultIsNotAsciiCapable" in its
+ // extra value is selected if and only if all other selected IMEs are not AsciiCapable.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoJa); // not ASCII capable
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_JA_JP, imi);
+ assertEquals(3, result.size());
+ verifyEquality(nonAutoJa, result.get(0));
+ verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, result.get(1));
+ verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2));
+ }
+
+ // Make sure that 3-letter language code can be handled.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoFil);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FIL_PH, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoFil, result.get(0));
+ }
+
+ // Make sure that we never end up matching "fi" (finnish) with "fil" (filipino).
+ // Also make sure that the first subtype will be used as the last-resort candidate.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoFil);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FI, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoJa, result.get(0));
+ }
+
+ // Make sure that "in" and "id" conversion is taken into account.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoIn);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoIn, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoIn);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoIn, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoId);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoId, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoId);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoId, result.get(0));
+ }
+ }
+
+ @SmallTest
+ public void testContainsSubtypeOf() throws Exception {
+ final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+
+ final boolean CHECK_COUNTRY = true;
+
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
+ SUBTYPE_MODE_VOICE));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
+ SUBTYPE_MODE_VOICE));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
+ SUBTYPE_MODE_ANY));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
+ SUBTYPE_MODE_ANY));
+
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that 3-letter language code ("fil") can be handled.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFil);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that 3-letter language code ("fil_PH") can be handled.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFilPH);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that a subtype whose locale is "in" can be queried with "id".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoIn);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that a subtype whose locale is "id" can be queried with "in".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoId);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ // TODO: This should be true but the current behavior is broken.
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ // TODO: This should be true but the current behavior is broken.
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+ }
+
+ private ArrayList<InputMethodSubtype> callGetImplicitlyApplicableSubtypesLockedWithLocale(
+ final Locale locale, final InputMethodInfo imi) {
+ final Context context = getInstrumentation().getTargetContext();
+ final Locale initialLocale = context.getResources().getConfiguration().locale;
+ try {
+ context.getResources().getConfiguration().setLocale(locale);
+ return InputMethodUtils.getImplicitlyApplicableSubtypesLocked(context.getResources(),
+ imi);
+ } finally {
+ context.getResources().getConfiguration().setLocale(initialLocale);
+ }
+ }
+
private void assertDefaultEnabledImes(final ArrayList<InputMethodInfo> preinstalledImes,
final Locale systemLocale, final boolean isSystemReady, String... expectedImeNames) {
final Context context = getInstrumentation().getTargetContext();
- final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesUnderWithLocale(
+ final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesWithLocale(
context, isSystemReady, preinstalledImes, systemLocale));
assertEquals(expectedImeNames.length, actualImeNames.length);
for (int i = 0; i < expectedImeNames.length; ++i) {
@@ -184,7 +603,7 @@
}
}
- private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesUnderWithLocale(
+ private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesWithLocale(
final Context context, final boolean isSystemReady,
final ArrayList<InputMethodInfo> imis, final Locale locale) {
final Locale initialLocale = context.getResources().getConfiguration().locale;
@@ -210,11 +629,15 @@
for (int subtypeIndex = 0; subtypeIndex < expected.getSubtypeCount(); ++subtypeIndex) {
final InputMethodSubtype expectedSubtype = expected.getSubtypeAt(subtypeIndex);
final InputMethodSubtype actualSubtype = actual.getSubtypeAt(subtypeIndex);
- assertEquals(expectedSubtype, actualSubtype);
- assertEquals(expectedSubtype.hashCode(), actualSubtype.hashCode());
+ verifyEquality(expectedSubtype, actualSubtype);
}
}
+ private static void verifyEquality(InputMethodSubtype expected, InputMethodSubtype actual) {
+ assertEquals(expected, actual);
+ assertEquals(expected.hashCode(), actual.hashCode());
+ }
+
private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name,
CharSequence label, boolean isAuxIme, boolean isDefault,
List<InputMethodSubtype> subtypes) {
@@ -236,13 +659,27 @@
private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
- boolean isAsciiCapable) {
+ boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) {
+
+ final StringBuilder subtypeExtraValue = new StringBuilder();
+ if (isEnabledWhenDefaultIsNotAsciiCapable) {
+ subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
+ subtypeExtraValue.append(EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ }
+
+ // TODO: Remove following code. InputMethodSubtype#isAsciiCapable() has been publicly
+ // available since API level 19 (KitKat). We no longer need to rely on extra value.
+ if (isAsciiCapable) {
+ subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
+ subtypeExtraValue.append(EXTRA_VALUE_ASCII_CAPABLE);
+ }
+
return new InputMethodSubtypeBuilder()
.setSubtypeNameResId(0)
.setSubtypeIconResId(0)
.setSubtypeLocale(locale)
.setSubtypeMode(mode)
- .setSubtypeExtraValue("")
+ .setSubtypeExtraValue(subtypeExtraValue.toString())
.setIsAuxiliary(isAuxiliary)
.setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype)
.setIsAsciiCapable(isAsciiCapable)
@@ -253,10 +690,12 @@
ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO,
- !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme",
"dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes));
}
@@ -268,33 +707,39 @@
ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO,
- !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0",
"dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO,
- !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1",
"dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2",
"dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme",
"dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes));
}
@@ -321,7 +766,8 @@
final boolean isDefaultIme = false;
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX,
- IS_AUTO, !IS_ASCII_CAPABLE));
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice",
"com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme,
subtypes));
@@ -332,9 +778,11 @@
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
// TODO: This subtype should be marked as IS_ASCII_CAPABLE
subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi",
"com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -345,7 +793,8 @@
final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin",
"com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -356,7 +805,8 @@
final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean",
"com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -368,13 +818,17 @@
new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin",
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -385,9 +839,11 @@
final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese",
"com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX,
isDefaultIme, subtypes));
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index d212b06..75f541a 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -516,23 +516,41 @@
<em>finished_asset</em>.png
drawable-xxhdpi/...
<em>finished_asset</em>.png
+
+ mipmap-ldpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-mdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-hdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxxhdpi/...
+ <em>finished_launcher_asset</em>.png
</pre>
<p>For more information about how to save resources in the application project,
see <a href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a>.
</p>
+<p> For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</p>
<h3 id="xxxhdpi-launcher">Provide an xxx-high-density launcher icon</h3>
-<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest density
+<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest density
launcher icon image is already extra-extra-high density, the scaling process will make it appear
-less crisp. So you should provide a higher density launcher icon in the <code>drawable-xxxhdpi
+less crisp. So you should provide a higher density launcher icon in the <code>mipmap-xxxhdpi
</code> directory, which the system uses instead of scaling up a smaller version of the icon.</p>
-<p class="note"><strong>Note:</strong> the <code>drawable-xxxhdpi</code> qualifier is necessary only
-to provide a launcher icon that can appear larger than usual on an xxhdpi device. You do not need to
-provide xxxhdpi assets for all your app's images.</p>
+<p class="note"><strong>Note:</strong> The <code>mipmap-xxxhdpi</code> qualifier is necessary
+only to provide a launcher icon that can appear larger than usual on an xxhdpi device. It is best
+practice to place all your launcher icons in the <code>res/mipmap-[density]/</code> folders. This
+enables your app to display launcher icons that have a higher density than the device, without
+scaling up a lower density version of the icon. You do not need to provide xxxhdpi assets for all
+your app's images.</p>
<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> for
more information.</p>
diff --git a/docs/html/google/gcm/c2dm.jd b/docs/html/google/gcm/c2dm.jd
index fc95c2b..6ae7c1a 100644
--- a/docs/html/google/gcm/c2dm.jd
+++ b/docs/html/google/gcm/c2dm.jd
@@ -75,7 +75,6 @@
<dt><strong>Canonical registration ID</strong></dt>
<dd>There may be situations where the server ends up with 2 registration IDs for the same device. If the GCM response contains a registration ID, simply replace the registration ID you have with the one provided. With this feature your application doesn't need to send the device ID to your server anymore. For more information, see <a href="adv.html#canonical">Advanced Topics</a>.</dd>
</dl>
-<p>GCM also provides client and server <a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a> to make writing your code easier.</p>
<h3 id="interop">Relationship between C2DM and GCM</h3>
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index 052cf75..e3cacf9 100644
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -232,7 +232,7 @@
1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
</pre>
-<p>Google Plays sends a response to your {@link android.app.PendingIntent} to the {@link android.app.Activity#onActivityResult onActivityResult} method of your application. The {@link android.app.Activity#onActivityResult onActivityResult} method will have a result code of {@code Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To see the types of order information that is returned in the response {@link android.content.Intent}, see <a href="{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app Billing Reference</a>.</p>
+<p>Google Play sends a response to your {@link android.app.PendingIntent} to the {@link android.app.Activity#onActivityResult onActivityResult} method of your application. The {@link android.app.Activity#onActivityResult onActivityResult} method will have a result code of {@code Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To see the types of order information that is returned in the response {@link android.content.Intent}, see <a href="{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app Billing Reference</a>.</p>
<p>The purchase data for the order is a String in JSON format that is mapped to the {@code INAPP_PURCHASE_DATA} key in the response {@link android.content.Intent}, for example:
<pre>
@@ -243,11 +243,19 @@
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
- "purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
+ "purchaseToken":<em>"opaque-token-up-to-1000-characters"</em>
}'
</pre>
</p>
+<p class="note"><strong>Note:</strong> Google Play generates a token for the
+purchase. This token is an opaque character sequence that may be up to 1,000
+characters long. Pass this entire token to other methods, such as when you
+consume the purchase, as described in
+<a href="{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
+a Purchase</a>. Do not abbreviate or truncate this token; you must save and
+return the entire token.</p>
+
<p>Continuing from the previous example, you get the response code, purchase data, and signature from the response {@link android.content.Intent}.</p>
<pre>
@Override
diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd
index 902c2c6..da9178d 100644
--- a/docs/html/google/play/billing/billing_reference.jd
+++ b/docs/html/google/play/billing/billing_reference.jd
@@ -202,7 +202,12 @@
</tr>
<tr>
<td>{@code purchaseToken}</td>
- <td>A token that uniquely identifies a purchase for a given item and user pair. </td>
+ <td>A token that uniquely identifies a purchase for a given item and user
+ pair. This token may be up to 1,000 characters long.
+ Pass this entire token to other methods, such as when you consume the
+ purchase (as described in
+<a href="{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
+ a Purchase</a>). Do not abbreviate or truncate this token.</td>
</tr>
</table>
</p>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 7ebda53..b6f1c49 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -1,5 +1,5 @@
page.title=Supporting Multiple Screens
-page.metaDescription=Nanaging UIs for the best display on multiple screen sizes.
+page.metaDescription=Managing UIs for the best display on multiple screen sizes.
meta.tags="multiple screens"
@jd:body
@@ -348,13 +348,13 @@
<code>hdpi</code> (high), <code>xhdpi</code> extra-high), <code>xxhdpi</code>
(extra-extra-high), and <code>xxxhdpi</code> (extra-extra-extra-high). For example, bitmaps
for high-density screens should go in {@code drawable-hdpi/}.</p>
- <p class="note" id="xxxhdpi-note"><strong>Note:</strong> the <code>drawable-xxxhdpi</code>
+ <p class="note" id="xxxhdpi-note"><strong>Note:</strong> The <code>mipmap-xxxhdpi</code>
qualifier is necessary only to provide a launcher icon that can appear larger than usual on an
xxhdpi device. You do not need to provide xxxhdpi assets for all your app's images.</p>
<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest
density launcher icon image is already extra-extra-high-density, the scaling process will make it
appear less crisp. So you should provide a higher density launcher icon in the
-<code>drawable-xxxhdpi</code> directory, which the system uses instead of scaling up a smaller
+<code>mipmap-xxxhdpi</code> directory, which the system uses instead of scaling up a smaller
version of the icon.</p>
<p>See <a href="{@docRoot}design/style/iconography.html#xxxhdpi-launcher">Provide an
xxx-high-density launcher icon</a> for more information. You should not use the
@@ -362,6 +362,16 @@
</li>
</ul>
+<p class="note"><strong>Note:</strong> Place all your launcher icons in the
+<code>res/mipmap-[density]/</code> folders, rather than the <code>res/drawable-[density]/</code>
+folders. The Android system retains the resources in these density-specific folders, such as
+mipmap-xxxhdpi, regardless of the screen resolution of the device where your app is installed. This
+behavior allows launcher apps to pick the best resolution icon for your app to display on the home
+screen. For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.
+</p>
+
+
<p>The size and density configuration qualifiers correspond to the generalized sizes and densities
described in <a href="#range">Range of screens supported</a>, above.</p>
@@ -538,9 +548,9 @@
sizes and densities, see <a href="#range">Range of Screens Supported</a>, earlier in this
document.</p>
-<p>For example, the following is a list of resource directories in an application that
-provides different layout designs for different screen sizes and different bitmap drawables
-for medium, high, and extra-high-density screens.</p>
+<p>For example, the following application resource directories provide different layout designs
+for different screen sizes and different drawables. Use the <code>mipmap/</code> folders for
+launcher icons.</p>
<pre class="classic">
res/layout/my_layout.xml // layout for normal screen size ("default")
@@ -548,10 +558,16 @@
res/layout-xlarge/my_layout.xml // layout for extra-large screen size
res/layout-xlarge-land/my_layout.xml // layout for extra-large in landscape orientation
-res/drawable-mdpi/my_icon.png // bitmap for medium-density
-res/drawable-hdpi/my_icon.png // bitmap for high-density
-res/drawable-xhdpi/my_icon.png // bitmap for extra-high-density
-res/drawable-xxhdpi/my_icon.png // bitmap for extra-extra-high-density
+res/drawable-mdpi/graphic.png // bitmap for medium-density
+res/drawable-hdpi/graphic.png // bitmap for high-density
+res/drawable-xhdpi/graphic.png // bitmap for extra-high-density
+res/drawable-xxhdpi/graphic.png // bitmap for extra-extra-high-density
+
+res/mipmap-mdpi/my_icon.png // launcher icon for medium-density
+res/mipmap-hdpi/my_icon.png // launcher icon for high-density
+res/mipmap-xhdpi/my_icon.png // launcher icon for extra-high-density
+res/mipmap-xxhdpi/my_icon.png // launcher icon for extra-extra-high-density
+res/mipmap-xxxhdpi/my_icon.png // launcher icon for extra-extra-extra-high-density
</pre>
<p>For more information about how to use alternative resources and a complete list of
@@ -560,7 +576,7 @@
Providing Alternative Resources</a>.</p>
<p>Be aware that, when the Android system picks which resources to use at runtime, it uses
-certain logic to determing the "best matching" resources. That is, the qualifiers you use don't
+certain logic to determine the "best matching" resources. That is, the qualifiers you use don't
have to exactly match the current screen configuration in all cases in order for the system to
use them. Specifically, when selecting resources based on the size qualifiers, the system will
use resources designed for a screen smaller than the current screen if there are no resources
@@ -703,10 +719,10 @@
smallest width your layout supports once it's complete.</p>
<p class="note"><strong>Note:</strong> Remember that all the figures used with these new size APIs
-are density-indpendent pixel (dp) values and your layout dimensions should also always be defined
+are density-independent pixel (dp) values and your layout dimensions should also always be defined
using dp units, because what you care about is the amount of screen space available after the system
accounts for screen density (as opposed to using raw pixel resolution). For more information about
-density-indpendent pixels, read <a href="#terms">Terms and concepts</a>, earlier in this
+density-independent pixels, read <a href="#terms">Terms and concepts</a>, earlier in this
document.</p>
@@ -728,7 +744,7 @@
a part of your application's window space, although your layout does not declare it, so it reduces
the space available for your layout and you must account for it in your design.</p>
-<p class="table-caption"><strong>Table 2.</strong> New configuration qualifers for screen size
+<p class="table-caption"><strong>Table 2.</strong> New configuration qualifiers for screen size
(introduced in Android 3.2).</p>
<table>
<tr><th>Screen configuration</th><th>Qualifier values</th><th>Description</th></tr>
@@ -745,7 +761,7 @@
use this qualifier to ensure that, regardless of the screen's current orientation, your
application's has at least {@code <N>} dps of width available for its UI.</p>
<p>For example, if your layout requires that its smallest dimension of screen area be at
-least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
+least 600 dp at all times, then you can use this qualifier to create the layout resources, {@code
res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived
height or width. The smallestWidth is a fixed screen size characteristic of the device; <strong>the
@@ -851,7 +867,7 @@
res/layout-sw720dp/main_activity.xml # For 10” tablets (720dp wide and bigger)
</pre>
-<p>Notice that the previous two sets of example resources use the "smallest width" qualifer, {@code
+<p>Notice that the previous two sets of example resources use the "smallest width" qualifier, {@code
sw<N>dp}, which specifies the smallest of the screen's two sides, regardless of the
device's current orientation. Thus, using {@code sw<N>dp} is a simple way to specify the
overall screen size available for your layout by ignoring the screen's orientation.</p>
@@ -1392,4 +1408,4 @@
<p>For more information about creating AVDs from the command line, see <a
href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing AVDs from the
-Command Line</a>.</p>
\ No newline at end of file
+Command Line</a>.</p>
diff --git a/docs/html/guide/topics/resources/available-resources.jd b/docs/html/guide/topics/resources/available-resources.jd
index 19babee..db1bf8d 100644
--- a/docs/html/guide/topics/resources/available-resources.jd
+++ b/docs/html/guide/topics/resources/available-resources.jd
@@ -29,6 +29,7 @@
<dt><a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a></dt>
<dd>Define various graphics with bitmaps or XML.<br/>
Saved in {@code res/drawable/} and accessed from the {@code R.drawable} class.</dd>
+
<dt><a href="{@docRoot}guide/topics/resources/layout-resource.html">Layout Resource</a></dt>
<dd>Define the layout for your application UI.<br/>
Saved in {@code res/layout/} and accessed from the {@code R.layout} class.</dd>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 6d9527f..fc79970 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -60,18 +60,24 @@
MyActivity.java </span>
res/
drawable/ <span style="color:black">
- icon.png </span>
+ graphic.png </span>
layout/ <span style="color:black">
main.xml
info.xml</span>
+ mipmap/ <span style="color:black">
+ icon.png </span>
values/ <span style="color:black">
strings.xml </span>
</pre>
<p>As you can see in this example, the {@code res/} directory contains all the resources (in
-subdirectories): an image resource, two layout resources, and a string resource file. The resource
+subdirectories): an image resource, two layout resources, {@code mipmap/} directories for launcher
+icons, and a string resource file. The resource
directory names are important and are described in table 1.</p>
+<p class="note"><strong>Note:</strong> For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</p>
+
<p class="table-caption" id="table1"><strong>Table 1.</strong> Resource directories
supported inside project {@code res/} directory.</p>
@@ -104,6 +110,7 @@
<tr>
<td><code>drawable/</code></td>
+
<td><p>Bitmap files ({@code .png}, {@code .9.png}, {@code .jpg}, {@code .gif}) or XML files that
are compiled into the following drawable resource subtypes:</p>
<ul>
@@ -119,6 +126,13 @@
</tr>
<tr>
+ <td><code>mipmap/</code></td>
+ <td>Drawable files for different launcher icon densities. For more information on managing
+ launcher icons with {@code mipmap/} folders, see
+ <a href="{@docRoot}tools/project/index.html#mipmap">Managing Projects Overview</a>.</td>
+ </tr>
+
+ <tr>
<td><code>layout/</code></td>
<td>XML files that define a user interface layout.
See <a href="layout-resource.html">Layout Resource</a>.</td>
diff --git a/docs/html/images/tools/projectview-p1.png b/docs/html/images/tools/projectview-p1.png
new file mode 100644
index 0000000..f5fae63
--- /dev/null
+++ b/docs/html/images/tools/projectview-p1.png
Binary files differ
diff --git a/docs/html/images/tools/projectview-p2.png b/docs/html/images/tools/projectview-p2.png
new file mode 100644
index 0000000..9e52540
--- /dev/null
+++ b/docs/html/images/tools/projectview-p2.png
Binary files differ
diff --git a/docs/html/images/tools/studio-inspection-scope.png b/docs/html/images/tools/studio-inspection-scope.png
deleted file mode 100644
index e69de29..0000000
--- a/docs/html/images/tools/studio-inspection-scope.png
+++ /dev/null
diff --git a/docs/html/images/tools/studio-inspections-config.png b/docs/html/images/tools/studio-inspections-config.png
index e69de29..e41afa1 100644
--- a/docs/html/images/tools/studio-inspections-config.png
+++ b/docs/html/images/tools/studio-inspections-config.png
Binary files differ
diff --git a/docs/html/images/tools/studio-mipmap-folders.png b/docs/html/images/tools/studio-mipmap-folders.png
new file mode 100644
index 0000000..3e99180
--- /dev/null
+++ b/docs/html/images/tools/studio-mipmap-folders.png
Binary files differ
diff --git a/docs/html/images/tools/studio-project-layout.png b/docs/html/images/tools/studio-project-layout.png
index 880c233..7339c3f 100644
--- a/docs/html/images/tools/studio-project-layout.png
+++ b/docs/html/images/tools/studio-project-layout.png
Binary files differ
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index af6f6b8..a43ba3c 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -4,27 +4,27 @@
header.hide=1
page.metaDescription=Download the official Android IDE and developer tools to build apps for Android phones, tablets, wearables, TVs, and more.
-studio.version=1.0.1
+studio.version=1.1.0
-studio.linux_bundle_download=android-studio-ide-135.1641136-linux.zip
-studio.linux_bundle_bytes=243917559
-studio.linux_bundle_checksum=7c8f2d0cec21b98984cdba45ab5a25f26d67f23a
+studio.linux_bundle_download=android-studio-ide-135.1740770-linux.zip
+studio.linux_bundle_bytes=259336386
+studio.linux_bundle_checksum=e8d166559c50a484f83ebfec6731cc0e3f259208
-studio.mac_bundle_download=android-studio-ide-1641136.dmg
-studio.mac_bundle_bytes=245729073
-studio.mac_bundle_checksum=49506ba2cf6b56be4f7d07e6a00c4ec3ba2249d5
+studio.mac_bundle_download=android-studio-ide-135.1740770-mac.dmg
+studio.mac_bundle_bytes=261303345
+studio.mac_bundle_checksum=f9745d0fec1eefd498f6160a2d6a1b5247d4cda3
-studio.win_bundle_exe_download=android-studio-bundle-135.1641136.exe
-studio.win_bundle_exe_bytes=868344232
-studio.win_bundle_exe_checksum=9c1c8ea6aa17fb74e0593c62fd48ee62a8950be7
+studio.win_bundle_exe_download=android-studio-bundle-135.1740770-windows.exe
+studio.win_bundle_exe_bytes=856233768
+studio.win_bundle_exe_checksum=7484b9989d2914e1de30995fbaa97a271a514b3f
-studio.win_notools_exe_download=android-studio-ide-135.1641136.exe
-studio.win_notools_exe_bytes=260272840
-studio.win_notools_exe_checksum=464d1c5497ab3d1bdef441365791ab36c89cd5ae
+studio.win_notools_exe_download=android-studio-ide-135.1740770-windows.exe
+studio.win_notools_exe_bytes=242135128
+studio.win_notools_exe_checksum=5ea77661cd2300cea09e8e34f4a2219a0813911f
-studio.win_bundle_download=android-studio-ide-135.1641136-windows.zip
-studio.win_bundle_bytes=246249059
-studio.win_bundle_checksum=6d6856aca83f6ff747ca40b10f70edfbbcccd91c
+studio.win_bundle_download=android-studio-ide-135.1740770-windows.zip
+studio.win_bundle_bytes=261667054
+studio.win_bundle_checksum=e903f17cc6a57c7e3d460c4555386e3e65c6b4eb
diff --git a/docs/html/sdk/installing/adding-packages.jd b/docs/html/sdk/installing/adding-packages.jd
index b8d8925..58a8065 100644
--- a/docs/html/sdk/installing/adding-packages.jd
+++ b/docs/html/sdk/installing/adding-packages.jd
@@ -72,7 +72,7 @@
<li>Windows: Double-click the <code>SDK Manager.exe</code> file at the root of the Android
SDK directory.</li>
<li>Mac/Linux: Open a terminal and navigate to the <code>tools/</code> directory in the
- Android SDK, then execute <code>android sdk</code>.</li>
+ location where the Android SDK was installed, then execute <code>android sdk</code>.</li>
</ul>
</li>
</ul>
diff --git a/docs/html/sdk/installing/create-project.jd b/docs/html/sdk/installing/create-project.jd
index 5082537..68fd572 100644
--- a/docs/html/sdk/installing/create-project.jd
+++ b/docs/html/sdk/installing/create-project.jd
@@ -71,7 +71,7 @@
<h3 id="Step2SelectFormFactor">Step 2: Select Form Factors and API Level</h2>
<p>The next window lets you select the form factors supported by your app, such as phone, tablet,
-TV, Wear, and Google Glass. The selected form factors become the application modules witin the
+TV, Wear, and Google Glass. The selected form factors become the application modules within the
project. For each form factor, you can also select the API Level for that app. To get more information,
click <strong>Help me choose</strong>.</p>
@@ -220,7 +220,7 @@
along with the other modules. </p>
<p> You can easily change an existing application module to a library module by changing the
- plugin assignment in the <strong>build.gradle</strong> file to <em>com.android.libary</em>.</p>
+ plugin assignment in the <strong>build.gradle</strong> file to <em>com.android.library</em>.</p>
<pre>
apply plugin: 'com.android.application'
@@ -287,7 +287,7 @@
<ol>
<li>Make sure that both the module library and the application module that depends on it are
- in your proejct. If one of the modules is missing, import it into your project.</li>
+ in your project. If one of the modules is missing, import it into your project.</li>
<li>In the project view, right-click the dependent module and select
<strong>Open</strong> > <strong>Module Settings</strong>.</li>
@@ -359,39 +359,38 @@
per resource type.</li>
</ul>
-<div style="float:right;margin-left:30px;width:240px">
-<img src="{@docRoot}images/tools/projectview01.png" alt="" width="220" height="264"/>
-<p class="img-caption"><strong>Figure 9:</strong> Show the Android project view.</p>
-</div>
-<h2 id="enable-view">Enable and use the Android Project View</h2>
+<h2 id="enable-view">Use the Android Project View</h2>
-<p>The Android project view is not yet enabled by default. To show the Android project view,
-click <strong>Project</strong> and select <strong>Android</strong>, as shown in figure 9.</p>
-
-<p>The Android project view shows all the build files at the top level of the project hierarchy
-under <strong>Gradle Scripts</strong>. Each project module appears as a folder at the top
-level of the project hierarchy and contains these three elements at the top level:</p>
+<p>The <em>Android</em> project view is enabled by default and shows all the build files at
+the top level of the project hierarchy under <strong>Gradle Scripts</strong>. The project module
+appears as a folder at the top level of the project hierarchy and contains these three elements
+at the top level:</p>
<ul>
-<li><code>java/</code> - Source files for the module.</li>
<li><code>manifests/</code> - Manifest files for the module.</li>
+<li><code>java/</code> - Source files for the module.</li>
<li><code>res/</code> - Resource files for the module.</li>
</ul>
-<p>Figure 10 shows how the Android project view groups all the instances of the
+<p>Notice how the Android project view groups all instances of the
<code>ic_launcher.png</code> resource for different screen densities under the same element.</p>
<p class="note"><strong>Note:</strong> The Android project view shows a hierarchy that helps you
work with Android projects by providing a flattened structure that highlights the most commonly
used files while developing Android applications. However, the project structure on disk differs
-from this representation.</p>
+from this representation and maintains the traditional project structure.</p>
-<img src="{@docRoot}images/tools/projectview03.png" alt=""
- style="margin-top:10px" width="650" height="508"/>
-<p class="img-caption"><strong>Figure 10:</strong> The traditional project view (left) and the
-Android project view (right).</p>
+<img src="{@docRoot}images/tools/projectview-p1.png" alt="" style="width:240px" "/>
+
+<img src="{@docRoot}images/tools/projectview-p2.png" alt="" style="width:240px" " />
+<p class="img-caption"><strong>Figure 10:</strong> Android and Traditional project view </p>
+
+
+
+
+
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index ee3bd95..d899ef3 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -121,7 +121,12 @@
<p>You may want to add {@code android-studio/bin/} to your PATH environmental
variable so that you can start Android Studio from any directory.</p>
</li>
- <li>Follow the setup wizard to install any necessary SDK tools.</li>
+ <li>If the SDK is not already installed, follow the setup wizard to install the SDK and any
+ necessary SDK tools.
+ <p class="note"><strong>Note:</strong> You may also need to install the ia32-libs,
+ lib32ncurses5-dev, and lib32stc++6 packages. These packages are required to support 32-bit apps
+ on a 64-bit machine. </p>
+ </li>
</ol>
</div><!-- end linux -->
diff --git a/docs/html/tools/debugging/debugging-ui.jd b/docs/html/tools/debugging/debugging-ui.jd
index f927d08..cf7e3ba 100644
--- a/docs/html/tools/debugging/debugging-ui.jd
+++ b/docs/html/tools/debugging/debugging-ui.jd
@@ -34,17 +34,17 @@
<h2>Related videos</h2>
<ol>
<li>
-<iframe title="Hierarchyviewer"
- width="210" height="160"
- src="//www.youtube.com/embed/PAgE7saQUUY?rel=0&hd=1"
+<iframe title="Hierarchyviewer"
+ width="210" height="160"
+ src="//www.youtube.com/embed/PAgE7saQUUY?rel=0&hd=1"
frameborder="0" allowfullscreen>
</iframe>
</li>
<li>
-<iframe title="Pixel Perfect"
- width="210" height="160"
- src="//www.youtube.com/embed/C45bMZGdN7Y?rel=0&hd=1"
- frameborder="0"
+<iframe title="Pixel Perfect"
+ width="210" height="160"
+ src="//www.youtube.com/embed/C45bMZGdN7Y?rel=0&hd=1"
+ frameborder="0"
allowfullscreen>
</iframe>
</li>
@@ -52,11 +52,10 @@
</div>
</div>
- <p>
-Sometimes your application's layout can slow down your application.
- To help debug issues in your layout, the Android SDK provides the Hierarchy Viewer and
- <code>lint</code> tools.
- </p>
+
+<p>Sometimes your application's layout can slow down your application.
+To help debug issues in your layout, the Android SDK provides the Hierarchy Viewer and
+<code><a href="{@docRoot}tools/help/lint.html">lint</a></code> tools. </p>
<p>The Hierarchy Viewer application allows you to debug and optimize your user interface. It
provides a visual representation of the layout's View hierarchy (the View Hierarchy window)
@@ -64,8 +63,10 @@
and a magnified view of the display (the Pixel Perfect window) to closely examine the pixels
in your layout.</p>
- <p>Android <code>lint</code> is a static code scanning tool that helps you optimize the layouts and layout
- hierarchies of your applications, as well as detect other common coding problems. You can run it against your layout files or resource
+ <p>Android <code><a href="{@docRoot}tools/help/lint.html">lint</a></code> is a static code
+ scanning tool that helps you optimize the layouts and layout
+ hierarchies of your applications, as well as detect other common coding problems. You can run it
+ against your layout files or resource
directories to quickly check for inefficiencies or other types of problems that could be
affecting the performance of your application.</p>
@@ -493,7 +494,10 @@
alt=""
height="600"/>
<p class="img-caption"><strong>Figure 4.</strong> The Pixel Perfect window</p>
+
+
<h2 id="lint">Using lint to Optimize Your UI</h2>
-<p>The Android {@code lint} tool lets you analyze the XML files that define your application's UI to find inefficiencies in the view hierarchy.</p>
-<p class="note"><strong>Note: </strong>The Android <code>layoutopt</code> tool has been replaced by the {@code lint} tool beginning in ADT and SDK Tools revision 16. The {@code lint} tool reports UI layout performance issues in a similar way as <code>layoutopt</code>, and detects additional problems.</p>
-<p>For more information about using {@code lint}, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a> and the <a href="{@docRoot}tools/help/lint.html">lint reference documentation</a>.</p>
+<p>The Android <a href="{@docRoot}tools/help/lint.html">lint</a> tool lets you analyze the XML
+files that define your application's UI to find inefficiencies in the view hierarchy.</p>
+<p class="note"><strong>Note: </strong>The Android <code>layoutopt</code> tool has been replaced by the {@code lint} tool beginning in SDK Tools revision 16. The {@code lint} tool reports UI layout performance issues in a similar way as <code>layoutopt</code>, and detects additional problems.</p>
+<p>For more information about using {@code lint}, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a> and the <a href="{@docRoot}tools/help/lint.html">lint tools help</a>.</p>
diff --git a/docs/html/tools/debugging/improving-w-lint.jd b/docs/html/tools/debugging/improving-w-lint.jd
index 7e238fa..ff94b7f 100644
--- a/docs/html/tools/debugging/improving-w-lint.jd
+++ b/docs/html/tools/debugging/improving-w-lint.jd
@@ -9,11 +9,11 @@
<ol>
<li><a href="#overview">Overview</a></li>
- <li><a href=#eclipse">Running lint from Eclipse</a></li>
+ <li><a href=#studio">Running lint from Android Studio</a></li>
<li><a href=#commandline">Running lint from the command-line</a></li>
<li><a href=#config">Configuring lint</a>
<ol>
- <LI><a href="#eclipse_config">Configuring lint in Eclipse</a></LI>
+ <LI><a href="#studio_config">Configuring lint in Android Studio</a></LI>
<LI><a href="#pref">Configuring the lint file</a></LI>
<LI><a href="#src">Configuring lint checking in Java and XML source files</a></LI>
</ol>
@@ -31,8 +31,15 @@
In addition to testing that your Android application meets its functional requirements, it's important to ensure that your code has no structural problems. Poorly structured code can impact the reliability and efficiency of your Android apps and make your code harder to maintain. For example, if your XML resource files contain unused namespaces, this takes up space and incurs unnecessary processing. Other structural issues, such as use of deprecated elements or API calls that are not supported by the target API versions, might lead to code failing to run correctly.</p>
<h2 id="overview">Overview</h2>
-<p>The Android SDK provides a code scanning tool called {@code lint} that can help you to easily identify and correct problems with the structural quality of your code, without having to execute the app or write any test cases. Each problem detected by the tool is reported with a description message and a severity level, so that you can quickly prioritize the critical improvements that need to be made. You can also configure a problem's severity level to ignore issues that are not relevant for your project, or raise the severity level. The tool has a command-line interface, so you can easily integrate it into your automated testing process.</p>
-<p>The {@code lint} tool checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization. You can run {@code lint} from the command-line or from the Eclipse environment.</p>
+<p>The Android SDK provides a code scanning tool called <a href="{@docRoot}tools/help/lint.html"><code>lint</code></a>
+that can help you to easily identify and correct problems with the structural quality of your code, without having to execute the app or write any test cases. Each problem detected by the tool is reported with a description message and a severity level, so that you can quickly prioritize the critical improvements that need to be made. You can also configure a problem's severity level to ignore issues that are not relevant for your project, or raise the severity level. The tool has a command-line interface, so you can easily integrate it into your automated testing process.</p>
+<p>The {@code lint} tool checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization. You can run {@code lint} from the command-line or from Android Studio.</p>
+
+<p class="note"><strong>Note:</strong> In Android Studio, additional
+<a href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection" class="external-link"
+target="_blank">IntelliJ code inspections</a> run when your code is compiled in Android Studio to
+streamline code review.</p>
+
<p>Figure 1 shows how the {@code lint} tool processes the application source files.</p>
<img id="Fig1" src="{@docRoot}images/tools/lint.png" alt="">
<p class="img-caption"><strong>Figure 1.</strong> Code scanning workflow with the {@code lint} tool</p>
@@ -42,25 +49,51 @@
<dt><b>The <code>lint.xml</code> file</b></dt>
<dd>A configuration file that you can use to specify any {@code lint} checks that you want to exclude and to customize problem severity levels.</dd>
<dt><b>The {@code lint} tool</b></dt>
-<dd>A static code scanning tool that you can run on your Android project from the command-line or from Eclipse. The {@code lint} tool checks for structural code problems that could affect the quality and performance of your Android application. It is strongly recommended that you correct any errors that {@code lint} detects before publishing your application.</dd>
+<dd>A static code scanning tool that you can run on your Android project from the command-line or Android Studio. The {@code lint} tool checks for structural code problems that could affect the quality and performance of your Android application. It is strongly recommended that you correct any errors that {@code lint} detects before publishing your application.</dd>
<dt><b>Results of {@code lint} checking</b></dt>
-<dd>You can view the results from {@code lint} in the console or in the <strong>Lint Warnings</strong> view in Eclipse. Each issue is identified by the location in the source files where it occurred and a description of the issue.</dd>
+<dd>You can view the results from {@code lint} in the console or in the <strong>Event Log</strong> in Android Studio. Each issue is identified by the location in the source files where it occurred and a description of the issue.</dd>
</dl>
-<p>The {@code lint} tool is automatically installed as part of the Android SDK Tools revision 16 or higher. If you want to use {@code lint} in the Eclipse environment, you must also install the Android Development Tools (ADT) Plugin for Eclipse revision 16 or higher. For more information about installing the SDK or the ADT Plugin for Eclipse, see <a href="http://developer.android.com/sdk/installing.html">Installing the SDK.</a></p>
+<p>The {@code lint} tool is automatically installed as part of the Android SDK Tools revision 16 or higher.</p>
-<h2 id="eclipse">Running lint from Eclipse</h2>
-<p>If the ADT Plugin is installed in your Eclipse environment, the {@code lint} tool runs automatically when you perform one of these actions:</p>
-<ul>
-<LI>Export an APK</LI>
-<LI>Edit and save an XML source file in your Android project (such as a manifest or layout file)</LI>
-<LI>Use the layout editor in Eclipse to make changes</LI>
-</ul>
-<p>Note that when you export an APK, {@code lint} only runs an automatic check for fatal errors and aborts the export if fatal errors are found. You can turn off this automatic checking from the <strong>Lint Error Checking</strong> page in Eclipse Preferences. </p>
-<p>The output is displayed in the <strong>Lint Warnings</strong> view. If the <strong>Lint Warnings</strong> view is not showing in the workbench, you can bring it up from the Eclipse menu by clicking <strong>Window > Show View > Other > Android > Lint Warnings</strong>.</p>
-<p>Figure 2 shows an example of the output in the Lint Warnings view.</p>
-<img id="Fig2" src="{@docRoot}images/tools/lint_output.png" alt="">
-<p class="img-caption"><strong>Figure 2.</strong> Sample output in the <strong>Lint Warnings</strong> view</p>
-<p>You can also run a {@code lint} scan manually on your Android project in Eclipse by right-clicking on the project folder in the Package Explorer > <strong>Android Tools > Run Lint: Check for Common Errors</strong>.</p>
+
+<h2 id="studio">Running lint in Android Studio</h2>
+<p>In Android Studio, the configured <code>lint</code> and
+IDE inspections run automatically whenever you build your app. The IDE inspections are
+configured along with the {@code lint} checks to run
+<a href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection" class="external-link"
+target="_blank">IntelliJ code inspections</a> to streamline code review.</p>
+
+<p class="note"><strong>Note:</strong> To view and modify inspection severity
+levels, use the <strong>File > Settings > Project Settings</strong> menu to open the
+<em>Inspection Configuration</em> page with a list of the supported inspections.</p>
+
+
+<p>With Android Studio, you can also run {@code lint} inspections for a specific build variant,
+or for all build variants from the <code>build.gradle</code> file. Add the
+<code>lintOptions</code> property to the <code>android</code> settings in the build file.
+This code snippet from a Gradle build file shows how to set the <code>quiet</code> option to
+<code>true</code> and the <code>abortOnError</code> option to <code>false</code>. </p>
+
+<pre>
+android {
+ lintOptions {
+ // set to true to turn off analysis progress reporting by lint
+ quiet true
+ // if true, stop the gradle build if errors are found
+ abortOnError false
+ // if true, only report errors
+ ignoreWarnings true
+ }
+ ...
+ }
+</pre>
+
+
+<p>To manually run inspections in Android Studio, from the application or right-click menu,
+choose <strong>Analyze > Inspect Code</strong>. The <em>Specify Inspections Scope</em> dialog
+appears so you can specify the desired inspection scope and profile.</p>
+
+
<h2 id="commandline">Running lint from the Command-Line</h2>
@@ -96,38 +129,45 @@
<p>By default, when you run a {@code lint} scan, the tool checks for all issues that are supported by {@code lint}. You can also restrict the issues for {@code lint} to check and assign the severity level for those issues. For example, you can disable {@code lint} checking for specific issues that are not relevant to your project and configure {@code lint} to report non-critical issues at a lower severity level.</p>
<p>You can configure {@code lint} checking at different levels:</p>
<ul>
-<LI>Globally, for all projects</LI>
-<li>Per project</li>
-<li>Per file</li>
-<li>Per Java class or method (by using the <code>@SuppressLint</code> annotation), or per XML element (by using the <code>tools:ignore</code> attribute.</li>
+<LI>Globally, for the entire project</LI>
+<li>Per project module</li>
+<li>Per production module</li>
+<li>Per test module</li>
+<li>Per open files</li>
+<li>Per class hierarchy</li>
+<li>Per Version Control System (VCS) scopes</li>
</ul>
-<h3 id="eclipse_config">Configuring lint in Eclipse</h3>
-<p>You can configure global, project-specific, and file-specific settings for {@code lint} from the Eclipse user interface.</p>
+<h3 id="studio_config">Configuring lint in Android Studio</h3>
+<p>Android Studio allows you to enable or disable individual inspections and configure
+project-global, directory-specific, and file-specific settings for {@code lint}.</p>
+
+<p>You can manage inspection profiles and configure inspection severity within Android Studio using
+the <strong>File > Settings > Project Settings</strong> menu to open the <em>Inspections</em>
+page with a list of the supported profiles and inspections.</p>
+<p><img src="{@docRoot}images/tools/studio-inspections-config.png" alt="" /> </p>
+<p class="img-caption"><strong>Figure 3.</strong> Inspection Configuration</p>
<h4>Global preferences</h4>
<ol>
-<LI>Open <strong>Window > Preferences > Android > Lint Error Checking</strong>.</LI>
-<li>Specify your preferences and click <b>OK</b>.</li>
-</ol>
-<p>These settings are applied by default when you run {@code lint} on your Android projects in Eclipse.</p>
+<li>To specify global project settings, select the project folder in the Project View and choose
+<strong>Analyze > Inspect Code</strong>.</li>
-<h4>Project and file-specific preferences</h4>
-<ol>
-<LI>Run the {@code lint} tool on your project by right-clicking on your project folder in the Package Explorer and selecting <strong>Android Tools > Run Lint: Check for Common Errors</strong>. This action brings up the <strong>Lint Warnings</strong> view which displays a list of issues that {@code lint} detected in your project.</LI>
-<li>From the <strong>Lint Warnings</strong> view, use the toolbar options to configure {@code lint} preferences for individual projects and files in Eclipse. The options you can select include:
-<ul>
-<LI><b>Suppress this error with an annotation/attribute</b> - If the issue appears in a Java class, the {@code lint} tool adds a <code>@SuppressLint</code> annotation to the method where the issue was detected. If the issue appears in an {@code .xml} file, {@code lint} inserts a <code>tools:ignore</code> attribute to disable checking for the {@code lint} issue in this file.</LI>
-<LI><b>Ignore in this file</b> - Disables checking for this {@code lint} issue in this file.</LI>
-<li><b>Ignore in this project</b> - Disables checking for this {@code lint} issue in this project.</li>
-<li><b>Always ignore</b> - Disables checking for this {@code lint} issue globally for all projects.</li>
-</ul>
-</li>
+<li>Specify your inspection scope and profile, and click <b>OK</b>.</li>
</ol>
-<p>If you select the second or third option, the {@code lint} tool automatically generates a <code>lint.xml</code> file with these configuration settings in your Android application project folder. </p>
+<p>The configured settings run the specified {@code lint} inspections. The {@code lint}
+inspections are also run whenever you build and run your Android project and modules.</p>
+
+<h4>Module and file-specific preferences</h4>
+<ol>
+<LI>Run the {@code lint} tool on your module by right-clicking on your module folder or file in the Project View and selecting <strong>Analyze > Inspect Code</strong>. This displays the {@code lint} inspection results
+with a list of issues that {@code lint} detected in your module.</LI>
+<li>From the <strong>Lint Warnings</strong> view, use the toolbar options to configure {@code lint} preferences for individual modules and files, and set the issue display options.</li>
+</ol>
+
<h3 id="pref">Configuring the lint file</h3>
-<p>You can specify your {@code lint} checking preferences in the <code>lint.xml</code> file. If you are creating this file manually, place it in the root directory of your Android project. If you are configuring {@code lint} preferences in Eclipse, the <code>lint.xml</code> file is automatically created and added to your Android project for you.</p>
+<p>You can specify your {@code lint} checking preferences in the <code>lint.xml</code> file. If you are creating this file manually, place it in the root directory of your Android project. If you are configuring {@code lint} preferences in Android Studio, the <code>lint.xml</code> file is automatically created and added to your Android project for you.</p>
<p>The <code>lint.xml</code> file consists of an enclosing <code><lint></code> parent tag that contains one or more children <code><issue></code> elements. Each <code><issue></code> is identified by a unique <code>id</code> attribute value, which is defined by {@code lint}.</p>
<pre>
<?xml version="1.0" encoding="UTF-8"?>
@@ -165,12 +205,9 @@
<h3 id="src">Configuring lint checking in Java and XML source files</h3>
<p>You can disable {@code lint} checking from your Java and XML source files.</p>
-<p class="note"><strong>Tip: </strong>If you are using Eclipse, you can use the <strong>Quick Fix</strong> feature to automatically add the annotation or attribute to disable {@code lint} checking to your Java or XML source files:
-<ol>
-<LI>Open the Java or XML file that has a {@code lint} warning or error in an Eclipse editor.</LI>
-<LI>Move your cursor to the location in the file where is {@code lint} issue is found, then press <code>Ctrl+1</code> to bring up the <strong>Quick Fix</strong> pop-up.</LI>
-<li>From the <strong>Quick Fix</strong> pop-up, select the action to add an annotation or attribute to ignore the {@code lint} issue.</li>
-</ol>
+<p class="note"><strong>Tip: </strong>If you are using Android Studio, you can use the
+<strong>File > Settings > Project Settings > Inspections</strong> feature to manage the
+{@code lint} checking to your Java or XML source files.
</p>
<h4>Configuring lint checking in Java</h4>
diff --git a/docs/html/tools/help/lint.jd b/docs/html/tools/help/lint.jd
index ba31f6d..0f52689 100644
--- a/docs/html/tools/help/lint.jd
+++ b/docs/html/tools/help/lint.jd
@@ -14,14 +14,23 @@
</div>
</div>
-<p>The Android {@code lint} tool is a static code analysis tool that checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization. </p>
-<p>For more information on running {@code lint}, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
+<p>The Android {@code lint} tool is a static code analysis tool that checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization.</p>
-<h2 id="syntax">Syntax</h2>
+<p>In Android Studio, the configured <code>lint</code> and other IDE inspections run automatically
+whenever you compile your program. You can also manually run inspections in Android Studio
+by selecting <strong>Analyze > Inspect Code</strong> from the application or right-click menu.
+The <em>Specify Inspections Scope</em> dialog appears so you can specify the desired inspection
+profile and scope.</p>
+
+<p>For more information on enabling {@code lint} inspections and running {@code lint},
+see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
+
+<h2 id="syntax">Command Line Syntax</h2>
<p>
<pre>lint [flags] <project directory></pre>
-For example, you can issue the following command to scan the Java and XML files under the {@code myproject} directory and its subdirectories. The result is displayed on the console.
+For example, you can issue the following command to scan the Java and XML files under the
+{@code myproject} directory and its subdirectories. The result is displayed on the console.
<pre>lint myproject</pre>
You can also use {@code lint} to check for a specific issue. For example, you can run the following command to scan the files under the {@code myproject} directory and its subdirectories to check for XML attributes missing the Android namespace prefix. The issue ID {@code MissingPrefix} tells lint to only scan for this issue.
@@ -172,7 +181,11 @@
<h2 id="config_keywords">Configuring Java and XML Source Files</h2>
<p>To configure lint checking, you can apply the following annotation or attribute to the source files in your Android project. </p>
<ul>
-<LI>To disable lint checking for a specific Java class or method, use the <code>@SuppressLint</code> annotation. </LI>
-<li>To disable lint checking for specific sections of your XML file, use the <code>tools:ignore</code> attribute. </li>
+<LI>To disable {@code lint} checking for a specific Java class or method, use the <code>@SuppressLint</code>
+annotation. </LI>
+<li>To disable {@code lint} checking for specific sections of your XML file, use the
+<code>tools:ignore</code> attribute. </li>
</ul>
-<p>You can also specify your lint checking preferences for a specific Android project in the lint.xml file. For more information on configuring lint, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
+<p>You can also specify your {@code lint} checking preferences for a specific Android project in
+the <code>lint.xml</code> file. For more information on configuring {@code lint}, see
+<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
diff --git a/docs/html/tools/help/sdk-manager.jd b/docs/html/tools/help/sdk-manager.jd
index b084237..0c77395 100644
--- a/docs/html/tools/help/sdk-manager.jd
+++ b/docs/html/tools/help/sdk-manager.jd
@@ -16,7 +16,7 @@
<li>On Windows, double-click the <code>SDK Manager.exe</code> file at the root of the Android
SDK directory.</li>
<li>On Mac or Linux, open a terminal and navigate to the <code>tools/</code> directory in the
-Android SDK, then execute <code>android sdk</code>.</li>
+location where the Android SDK is installed, then execute <code>android sdk</code>.</li>
</ul>
<p>You can select which packages you want to download by toggling the checkboxes on the left, then
diff --git a/docs/html/tools/projects/index.jd b/docs/html/tools/projects/index.jd
index 5f4f2cc..8665479 100644
--- a/docs/html/tools/projects/index.jd
+++ b/docs/html/tools/projects/index.jd
@@ -1,4 +1,6 @@
page.title=Managing Projects Overview
+meta.tags="project, mipmap"
+page.tags="project", "mipmap"
@jd:body
<div id="qv-wrapper">
@@ -8,7 +10,9 @@
<ol>
<li><a href="#ProjectFiles">Android Project Files</a></li>
<li><a href="#ApplicationModules">Android Application Modules</a></li>
-
+ <ol>
+ <li><a href="#mipmap">Managing Launcher Icons as mipmap Resources</a></li>
+ </ol>
<li><a href="#LibraryModules">Library Modules</a>
<ol>
<li><a href="#considerations">Development considerations</a></li>
@@ -230,7 +234,18 @@
focused). See the <a href=
"{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a> resource type.</dd>
- <dt><code>layout/</code></dt>
+
+ <dt><code>mipmap/</code></dt>
+
+ <dd>For app launcher icons. The Android system retains the resources in this folder
+ (and density-specific folders such as mipmap-xxxhdpi) regardless of the screen resolution
+ of the device where your app is installed. This behavior allows launcher apps to pick
+ the best resolution icon for your app to display on the home screen. For more information
+ about using the <code>mipmap</code> folders, see
+ <a href="#mipmap">Managing Launcher Icons as mipmap Resources</a>. </p>
+
+
+ <dt><code>layout/</code></dt>
<dd>XML files that are compiled into screen layouts (or part of a screen). See the <a href=
"{@docRoot}guide/topics/resources/layout-resource.html">Layout</a> resource type.</dd>
@@ -304,6 +319,46 @@
+<h2 id="mipmap">Managing Launcher Icons as mipmap Resources</h2>
+
+<p>Different home screen launcher apps on different devices show app launcher icons at various
+resolutions. When app resource optimization techniques remove resources for unused
+screen densities, launcher icons can wind up looking fuzzy because the launcher app has to upscale
+a lower-resolution icon for display. To avoid these display issues, apps should use the
+<code>mipmap/</code> resource folders for launcher icons. The Android system
+preserves these resources regardless of density stripping, and ensures that launcher apps can
+pick icons with the best resolution for display. </p>
+
+<p>Make sure launcher apps show a high-resolution icon for your app by moving all densities of your
+launcher icons to density-specific <code>res/mipmap/</code> folders
+(for example <code>res/mipmap-mdpi/</code> and <code>res/mipmap-xxxhdpi/</code>). The
+<code>mipmap/</code> folders replace the <code>drawable/</code> folders for launcher icons. For
+xxhpdi launcher icons, be sure to add the higher resolution xxxhdpi versions of the
+icons to enhance the visual experience of the icons on higher resolution devices.</p>
+
+<p class="note"><strong>Note:</strong> Even if you build a single APK for all devices, it is still
+best practice to move your launcher icons to the <code>mipmap/</code> folders.</p>
+
+
+<h3>Manifest update</h3>
+
+<p>When you move your launcher icons to the <code>mipmap-[density]</code> folders, change the
+launcher icon references in the <code>AndroidManifest.xml</code> file so your manifest references
+the <code>mipmap/</code> location. This example changes the manifest file to reference the
+<code>ic_launcher</code> icon in the <code>mipmap/</code> folder. </p>
+
+<pre>
+...
+<application android:name="ApplicationTitle"
+ android:label="@string/app_label"
+ android:icon="@mipmap/ic_launcher" >
+ ...
+</pre>
+
+
+
+
+
<h2 id="LibraryModules">Library Module</h2>
<div class="sidebox-wrapper">
diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd
index 74e8cf5..9e7721b 100644
--- a/docs/html/tools/studio/index.jd
+++ b/docs/html/tools/studio/index.jd
@@ -36,7 +36,7 @@
<li>Build variants and multiple <code>apk</code> file generation</li>
<li>Code templates to help you build common app features</li>
<li>Rich layout editor with support for drag and drop theme editing</li>
- <li>Lint tools to catch performance, usability, version compatibility, and other problems</li>
+ <li>{@code lint} tools to catch performance, usability, version compatibility, and other problems</li>
<li>ProGuard and app-signing capabilities</li>
<li>Built-in support for <a
href="http://developers.google.com/cloud/devtools/android_studio_templates/"
@@ -65,8 +65,8 @@
<h3 id="project-view"><em>Android</em> Project View</h3>
<p>By default, Android Studio displays your profile files in the <em>Android</em> project view. This
view shows a flattened version of your project's structure that provides quick access to the key
-source files of Android projects and helps you work with the new
-<a href="{@docRoot}sdk/installing/studio-build.html">Gradle-based build system</a>.
+source files of Android projects and helps you work with the
+<a href="{@docRoot}sdk/installing/studio-build.html">Gradle-based build system</a>.
The Android project view:</p>
<ul>
@@ -102,7 +102,7 @@
-<h3>New Project and Directory Structure</h3>
+<h3>Android Studio Project and Directory Structure</h3>
<p>When you use the <em>Project</em> view of a new project in Android Studio, you
should notice that the project structure appears different than you may be used to in Eclipse. Each
instance of Android Studio contains a project with one or more application modules. Each
@@ -120,6 +120,7 @@
<a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.</p>
+
<h3>Creating new files</h3>
<p>You can quickly add new code and resource files by clicking the appropriate directory in the
<strong>Project</strong> pane and pressing <code>ALT + INSERT</code> on Windows and Linux or
@@ -243,19 +244,28 @@
-<h3> Memory Monitor</h3>
+<h3>Memory Monitor</h3>
<p>Android Studio provides a memory monitor view so you can more easily monitor your
app's memory usage to find deallocated objects, locate memory leaks and track the amount of
memory the connected device is using. With your app running on a device or emulator, click the
<strong>Memory Monitor</strong> tab in the lower right corner to launch the memory monitor. </p>
<img src="{@docRoot}images/tools/studio-memory-monitor.png" />
- <p class="img-caption"><strong>Figure 4.</strong> Memory Monitor</p>
+ <p class="img-caption"><strong>Figure 5.</strong> Memory Monitor</p>
-<h3> New Lint inspections</h3>
-<p>Lint has several new checks to ensure:
+<h3>Code Inspections</h3>
+<p>In Android Studio, the configured <a href="{@docRoot}tools/help/lint.html"><code>lint</code></a> and
+other IDE inspections run automatically whenever you compile your program. In addition to the
+configured {@code lint} checks, additional
+<a href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection" class="external-link"
+target="_blank">IntelliJ code inspections</a>
+run to streamline code review.</p>
+
+
+<p>Android Studio enables several <code>lint</code> checks
+to ensure:
<ul>
<li><code> Cipher.getInstance()</code> is used with safe values</li>
<li>In custom Views, the associated declare-styleable for the custom view uses the same
@@ -268,44 +278,75 @@
<li>many others</li>
</ul>
-<p>Hovering over a Lint error displays the full issue explanation inline for easy error
+
+<p>Hovering over an inspection error displays the full issue explanation inline for easy error
resolution. There is also a helpful hyperlink at the end of the error message for additional
error information.</p>
-<p>With Android Studio, you can run Lint for a specific build variant, or for all build variants.
-You can configure Lint by adding a <em>lintOptions</em> property to the Android settings in the
-build.gradle file. </p>
+<p>With Android Studio, you can also run {@code lint} inspections for a specific build variant, or
+for all build variants. You can configure the {@code lint} inspections that run by adding a
+<code>lintOptions</code> property to the Android settings in the <code>build.gradle</code>
+file. </p>
- <pre>
- android {
- lintOptions {
- // set to true to turn off analysis progress reporting by lint
- quiet true
- // if true, stop the gradle build if errors are found
- abortOnError false
- // if true, only report errors
- ignoreWarnings true
- </pre>
+<pre>
+android {
+ lintOptions {
+ // set to true to turn off analysis progress reporting by lint
+ quiet true
+ // if true, stop the gradle build if errors are found
+ abortOnError false
+ // if true, only report errors
+ ignoreWarnings true
+ }
+</pre>
+
+
+<p>You can also manage inspection profiles and configure inspections within Android Studio.
+Choose <strong>File > Settings > Project Settings</strong>. The
+<em>Inspection Configuration</em> page appears with the supported inspections.</p>
+<p><img src="{@docRoot}images/tools/studio-inspections-config.png" alt="" /> </p>
+<p class="img-caption"><strong>Figure 5.</strong> Inspection Configuration</p>
+
+<p class="note"><strong>Note:</strong> If you wish to change the behavior of specific
+inspection notifications, you can change the inspection severity, for example from <em>warning</em>
+to <em>error</em>. </p>
+
+
+<p>To manually run inspections in Android Studio, choose <strong>Analyze > Inspect Code</strong>.
+The <em>Inspections Scope</em> dialog appears so you can specify the desired inspection profile and scope.</p>
+
+
+
+<h4>Running Inspections from the command line</h4>
+<p>You can also run {@code lint} inspections from the command line in your SDK directory. </p>
+<pre>
+sdk$ lint [flags] <project directories>
+</pre>
+
+<p class="note"><strong>Note:</strong> The {@code lint} <strong>--show</strong> and <strong>--list</strong>
+flags can be used to display the available issues and explanations. </p>
+
<p>For more information, see
-<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with Lint</a>.</p>
+<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with {@code lint}</a> and
+<a href="{@docRoot}tools/help/lint.html">lint tool</a>.</p>
<h3>Dynamic layout preview</h3>
<p>Android Studio allows you to work with layouts in both a <em>Design View</em> </p>
<p><img src="{@docRoot}images/tools/studio-helloworld-design.png" alt="" />
</p>
- <p class="img-caption"><strong>Figure 5.</strong> Hello World App with Design View</p>
+ <p class="img-caption"><strong>Figure 6.</strong> Hello World App with Design View</p>
<p>and a <em>Text View</em>. </p>
<p><img src="{@docRoot}images/tools/studio-helloworld-text.png" alt="" />
- <pclass="img-caption"><strong>Figure 6.</strong> Hello World App with Text View</p>
+ <pclass="img-caption"><strong>Figure 7.</strong> Hello World App with Text View</p>
<p>Easily select and preview layout changes for different device images, display
densities, UI modes, locales, and Android versions (multi-API version rendering).
<p><img src="{@docRoot}images/tools/studio-api-version-rendering.png" /></p>
- <p class="img-caption"><strong>Figure 7.</strong> API Version Rendering</p>
+ <p class="img-caption"><strong>Figure 8.</strong> API Version Rendering</p>
<p>From the Design View, you can drag and drop elements from the Palette to the Preview or
@@ -342,18 +383,19 @@
an optimized default Android Virtual Device (AVD) based on Android 5 (Lollipop) for speedy and
reliable emulation. </p>
<p><img src="{@docRoot}images/tools/studio-setup-wizard.png" /></p>
-<p class="img-caption"><strong>Figure 8.</strong> Setup Wizard</p>
+<p class="img-caption"><strong>Figure 9.</strong> Setup Wizard</p>
<h3>Expanded template and form factor support</h3>
-<p>Android Studio supports new templates for Google Services and expands the available device
+<p>Android Studio supports templates for Google Services and expands the available device
types. </p>
<h4> Android Wear and TV support</h4>
<p>For easy cross-platform development, the Project Wizard provides new templates for
creating your apps for Android Wear and TV. </p>
<p><img src="{@docRoot}images/tools/studio-tvwearsupport.png" />
- <p class="img-caption"><strong>Figure 9.</strong> New Form Factors</p>
+
+ <p class="img-caption"><strong>Figure 10.</strong> Supported Form Factors</p>
<p>During app creation, the Project Wizard also displays an API Level dialog to help you choose
the best <em>minSdkVersion</em> for your project.</p>
@@ -363,7 +405,7 @@
and create a cloud end-point is as easy as selecting <em>File > New Module > App Engine Java
Servlet Module</em> and specifying the module, package, and client names. </p>
<p><img src="{@docRoot}images/tools/studio-cloudmodule.png" /></p>
- <p class="img-caption"><strong>Figure 10.</strong> Setup Wizard</p>
+ <p class="img-caption"><strong>Figure 11.</strong> Setup Wizard</p>
@@ -514,24 +556,25 @@
<strong>Open Editor</strong> link. </p>
<img src="{@docRoot}images/tools/studio-translationeditoropen.png" />
- <p class="img-caption"><strong>Figure 11.</strong> Translation Editor</p>
+ <p class="img-caption"><strong>Figure 12.</strong> Translation Editor</p>
<h3> Editor support for the latest Android APIs</h3>
-<p>Android Studio supports the new
+<p>Android Studio supports the
<a href="{@docRoot}design/material/index.html">Material Design</a></li> themes, widgets, and
graphics, such as shadow layers and API version rendering (showing the layout across different
-UI versions). Also, the new drawable XML tags and attributes, such as <ripple>
+UI versions). Also, the drawable XML tags and attributes, such as <ripple>
and <animated-selector>, are supported.</p>
<h3 id="git-samples"> Easy access to Android code samples on GitHub</h3>
-<p>Clicking <strong>Import Samples</strong> from the <strong>File</strong> menu or Welcome page
+<p>Clicking <strong>Import Samples</strong> from the <strong>File</strong> menu or <em>Welcome</em> page
+
provides seamless access to Google code samples on GitHub.</p>
<p><img src="{@docRoot}images/tools/studio-samples-githubaccess.png" /></p>
- <p class="img-caption"><strong>Figure 12.</strong> Code Sample Access</p>
+ <p class="img-caption"><strong>Figure 13.</strong> Code Sample Access</p>
<p><img src="{@docRoot}images/tools/studio-sample-in-editor.png" /></p>
- <p class="img-caption"><strong>Figure 13.</strong> Imported Code Sample</p>
+ <p class="img-caption"><strong>Figure 14.</strong> Imported Code Sample</p>
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 71b93c0..79268a0 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -103,10 +103,13 @@
Activities</a> for more information.</p>
</div>
</div>
- <li>Under <strong>Add an activity to your project</strong>, select <strong>Blank Activity</strong>
- and click <strong>Next</strong>.</li>
- <li>Under <strong>Describe the new activity for your project</strong>, leave the fields as they
- are and click <strong>Finish</strong>.</li>
+ <li>Under <strong>Add an activity to <<em>template</em>></strong>, select <strong>Blank
+ Activity</strong> and click <strong>Next</strong>.</li>
+ <li>Under <strong>Choose options for your new file</strong>, change the
+ <strong>Activity Name</strong> to <em>MyActivity</em>. The <strong>Layout Name</strong> changes
+ to <em>activity_my</em>, and the <strong>Title</strong> to <em>MyActivity</em>. The
+ <strong>Menu Resource Name</strong> is <em>menu_my</em>.
+ <li>Click the <strong>Finish</strong> button to create the project.</li>
</ol>
<p>Your Android project is now a basic "Hello World" app that contains some default files. Take a
@@ -123,7 +126,7 @@
select the file you see the class definition for the activity you created. When you build and
run the app, the {@link android.app.Activity} class starts the activity and loads the layout file
that says "Hello World!"</dd>
- <dt><code>app/src/res/AndroidManifest.xml</code></dt>
+ <dt><code>app/src/main/AndroidManifest.xml</code></dt>
<dd>The <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest file</a> describes
the fundamental characteristics of the app and defines each of its components. You'll revisit
this file as you follow these lessons and add more components to your app.</dd>
@@ -159,13 +162,16 @@
<p>Note also the <code>/res</code> subdirectories that contain the
<a href="{@docRoot}guide/topics/resources/overview.html">resources</a> for your application:</p>
<dl>
- <dt><code>drawable-hdpi/</code></dt>
- <dd>Directory for drawable objects (such as bitmaps) that are designed for high-density
- (hdpi) screens. Other drawable directories contain assets designed for other screen densities.
+ <dt><code>drawable<em><density></em>/</code></dt>
+ <dd>Directories for drawable objects (such as bitmaps) that are designed for various densities,
+ such as medium-density (mdpi) and high-density (hdpi) screens. Other drawable directories
+ contain assets designed for other screen densities.
Here you'll find the ic_launcher.png that appears when you run the default app.</dd>
<dt><code>layout/</code></dt>
<dd>Directory for files that define your app's user interface like activity_my.xml,
discussed above, which describes a basic layout for the MyActivity class.</dd>
+ <dt><code>menu/</code></dt>
+ <dd>Directory for files that define your app's menu items.</dd>
<dt><code>values/</code></dt>
<dd>Directory for other XML files that contain a collection of resources, such as
string and color definitions. The strings.xml file defines the "Hello world!" string that
@@ -180,9 +186,9 @@
using the SDK tools from a command line:</p>
<ol>
- <li>Change directories into the Android SDK’s <code>tools/</code> path.</li>
+ <li>Change directories into the Android SDK’s <code>sdk/</code> path.</li>
<li>Execute:
-<pre class="no-pretty-print">android list targets</pre>
+<pre class="no-pretty-print">tools/android list targets</pre>
<p>This prints a list of the available Android platforms that you’ve downloaded for your SDK. Find
the platform against which you want to compile your app. Make a note of the target ID. We
recommend that you select the highest version possible. You can still build your app to
@@ -212,4 +218,3 @@
-
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index c09669f..fdf0d1f 100644
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -83,14 +83,37 @@
<h3>Run the app from a command line</h3>
-<ol>
- <li>Change directories to the root of your Android project and execute:
-<pre class="no-pretty-print">ant debug</pre></li>
- <li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
-<code>PATH</code> environment variable, then execute:
-<pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li>
- <li>On your device, locate <em>MyFirstApp</em> and open it.</li>
-</ol>
+<p>Open a command-line and navigate to the root of your project directory.
+ Use Gradle to build your project in debug mode, invoke the <code>assembleDebug</code> build task
+ using the Gradle wrapper script (<code>gradlew assembleRelease</code>).
+
+ <p>This creates your debug <code>.apk</code> file inside the module <code>build/</code>
+ directory, named <code>MyFirstApp-debug.apk</code>. </p>
+
+ <p>On Windows platforms, type this command:</p>
+
+<pre>
+> gradlew.bat assembleDebug
+</pre>
+
+<p>On Mac OS and Linux platforms, type these commands:</p>
+
+<pre>
+$ chmod +x gradlew
+$ ./gradlew assembleDebug
+</pre>
+
+ <p>After you build the project, the output APK for the app module is located in
+ <code>app/build/outputs/apk/</code>
+
+ <p class="note"><strong>Note:</strong> The first command (<code>chmod</code>) adds the execution
+ permission to the Gradle wrapper script and is only necessary the first time you build this
+ project from the command line.</p>
+
+ <p>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
+ <code>PATH</code> environment variable, then execute:
+ <pre class="no-pretty-print">adb install app/build/outputs/MyFirstApp-debug.apk</pre><p>
+ <p>On your device, locate <em>MyFirstApp</em> and open it.</p>
<p>That's how you build and run your Android app on a device!
To start developing, continue to the <a href="building-ui.html">next
@@ -114,12 +137,29 @@
<ol>
<li>Launch the Android Virtual Device Manager:
<ul>
- <li>In the Android Studio tool bar, click the Android Virtual Device Manager icon
- <img src="{@docRoot}images/tools/avd-manager-studio.png"
- style="vertical-align:baseline;margin:0; max-height:1em" />.</li>
- <li>From the command line, change directories to <code><sdk>/tools/</code> and execute:
- <pre class="no-pretty-print">android avd</pre></li>
+ <li>In Android Studio, select <strong>Tools > Android > AVD Manager</strong>, or click
+ the AVD Manager icon <img src="{@docRoot}images/tools/avd-manager-studio.png" style="vertical-align:bottom;margin:0;height:19px"> in the toolbar.</li>
+ <li>Or, from the command line, change directories to
+ <code>sdk/</code> and execute:
+ <pre class="no-pretty-print">tools/android avd</pre>
+ <p class="note"><strong>Note:</strong> The AVD Manager that appears
+ when launched from the command line is different from the version in
+ Android Studio, so the following instructions may not all apply.</p>
+ </li>
</ul>
+
+ <img src="{@docRoot}images/studio-avdmgr-firstscreen.png" alt=""
+ style="margin-top:1em">
+ <p class="img-caption"><strong>Figure 1.</strong> The AVD Manager main screen shows your current virtual devices.</p>
+
+ </li>
+ <li>On the AVD Manager main screen (figure 1), click <strong>Create Virtual Device</strong>.</li>
+ <li>In the Select Hardware window, select a device configuration, such as Nexus 6,
+ then click <strong>Next</strong>.
+ </li>
+ <li>Select the desired system version for the AVD and click <strong>Next</strong>.
+ </li>
+ <li>Verify the configuration settings, then click <strong>Finish</strong>.
</li>
<li>In the <strong>Android Virtual Device Manager</strong> window, click <strong>Create</strong>.</li>
<li>Enter an <strong>AVD Name</strong>.</li>
@@ -137,40 +177,33 @@
<h3>Run the app from Android Studio</h3>
<ol>
<li>In <strong>Android Studio</strong>, select your project and click <strong>Run</strong>
- <img src="{@docRoot}images/tools/as-run.png" style="vertical-align:baseline;margin:0; max-height:1em" />
- from the toolbar.</li>
+ <img src="{@docRoot}images/tools/as-run.png" style="vertical-align:baseline;margin:0; max-height:1em" /> from the toolbar.</li>
<li>In the <strong>Choose Device</strong> window, click the <strong>Launch emulator</strong> radio
button.</li>
<li>From the <strong>Android virtual device</strong> pull-down menu, select the emulator
you created, and click <strong>OK</strong>.</li>
</ol>
<p>It can take a few minutes for the emulator to load itself. You may have to unlock the screen.
- When you do, My First App appears on the emulator screen.</p>
+When you do, <em>My First App</em> appears on the emulator screen.</p>
<h3>Run your app from the command line</h3>
-
-<ol>
- <li>Change directories to the root of your Android project and execute:
- <pre class="no-pretty-print">ant debug</pre></li>
+ <ol>
+ <li>Build the project from the command line. The output APK for the app module is located in
+ <code>app/build/outputs/apk/</code>.</li>
<li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
- <code>PATH</code> environment variable, then execute:
- <pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li>
+ <code>PATH</code> environment variable.</li>
+ <li>Execute this command:
+ <p>
+ <pre class="no-pretty-print">adb install app/build/outputs/MyFirstApp-debug.apk</pre>
+ </p>
+ </li>
<li>On the emulator, locate <em>MyFirstApp</em> and open it.</li>
-</ol>
+ </ol>
-<p>That's how you build and run your Android app on the emulator!
+ <p>That's how you build and run your Android app on the emulator!
To start developing, continue to the <a href="building-ui.html">next
-lesson</a>.</p>
-
-
-
-
-
-
-
-
-
+ lesson</a>.</p>
diff --git a/docs/html/training/improving-layouts/optimizing-layout.jd b/docs/html/training/improving-layouts/optimizing-layout.jd
index 520ce56..003e7a2 100644
--- a/docs/html/training/improving-layouts/optimizing-layout.jd
+++ b/docs/html/training/improving-layouts/optimizing-layout.jd
@@ -126,13 +126,15 @@
<p>Most of this time difference is due to the use of {@code layout_weight} in the {@link
android.widget.LinearLayout} design, which can slow down the speed of measurement. It is just one
-example of how each layout has appropriate uses and you should carefully consider whether using
+example of how each layout has appropriate uses and you should carefully consider whether using
layout weight is necessary.</p>
<h2 id="Lint">Use Lint</h2>
-<p>It is always good practice to run the <a href="http://tools.android.com/tips/lint">Lint</a> tool on your layout files to search for possible view hierarchy optimizations. Lint has replaced the Layoutopt tool and has much greater functionality. Some examples of Lint <a
+<p>It is always good practice to run the <a href="{@docRoot}tools/help/lint.html">lint</a>
+tool on your layout files to search for possible view hierarchy optimizations. Lint has replaced
+the Layoutopt tool and has much greater functionality. Some examples of lint <a
href="http://tools.android.com/tips/lint-checks">rules</a> are:</p>
<ul>
@@ -143,11 +145,18 @@
<li>Deep layouts - Layouts with too much nesting are bad for performance. Consider using flatter layouts such as {@link android.widget.RelativeLayout} or {@link android.widget.GridLayout} to improve performance. The default maximum depth is 10.</li>
</ul>
-<p>Another benefit of Lint is that it is integrated into the Android Development Tools for Eclipse (ADT 16+). Lint automatically runs whenever you export an APK, edit and save an XML file or use the Layout Editor. To manually force Lint to run press the Lint button in the Eclipse toolbar.</p>
+<p>Another benefit of Lint is that it is integrated into Android Studio. Lint automatically runs
+whenever you compile your program. With Android Studio, you can also run lint inspections for a
+specific build variant, or for all build variants. </p>
-<img src="{@docRoot}images/training/lint_icon.png" alt="" />
+<p>You can also manage inspection profiles and configure inspections within Android Studio with the
+<strong>File>Settings>Project Settings</strong> option. The Inspection Configuration page
+appears with the supported inspections.</p>
+<p><img src="{@docRoot}images/tools/studio-inspections-config.png" alt="" /> </p>
+<p class="img-caption"><strong>Figure 5.</strong> Inspection Configuration</p>
-<p>When used inside Eclipse, Lint has the ability to automatically fix some issues, provide suggestions for others and jump directly to the offending code for review. If you don’t use Eclipse for your development, Lint can also be run from the command line. More information about Lint is available at <a href="http://tools.android.com/tips/lint">tools.android.com</a>.</p>
+<p>Lint has the ability to automatically fix some issues, provide suggestions for others and jump
+directly to the offending code for review.</p>
diff --git a/docs/html/training/multiscreen/screendensities.jd b/docs/html/training/multiscreen/screendensities.jd
index fcb65cc..64e70fd 100644
--- a/docs/html/training/multiscreen/screendensities.jd
+++ b/docs/html/training/multiscreen/screendensities.jd
@@ -28,6 +28,7 @@
<ul>
<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+ <li><a href="{@docRoot}design/style/iconography.html">Iconography</a></li>
<li><a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Icon Design
Guidelines</a></li>
</ul>
@@ -133,6 +134,28 @@
<p>Then, any time you reference <code>@drawable/awesomeimage</code>, the system selects the
appropriate bitmap based on the screen's dpi.</p>
+<p>Place your launcher icons in the <code>mipmap/</code> folders. </p>
+
+<pre>res/...
+ mipmap-ldpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-mdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-hdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxxhdpi/...
+ <em>finished_launcher_asset</em>.png
+</pre>
+
+<p class="note"><strong>Note:</strong> You should place all launcher icons in the
+<code>res/mipmap-[density]/</code> folders, rather than <code>drawable/</code> folders to ensure
+launcher apps use the best resolution icon. For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</p>
+
<p>For more tips and guidelines for creating icon assets for your application, see the <a
href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Icon Design
Guidelines</a>.</p>
diff --git a/docs/html/training/volley/request.jd b/docs/html/training/volley/request.jd
index d8ccab2..8a7dc62 100644
--- a/docs/html/training/volley/request.jd
+++ b/docs/html/training/volley/request.jd
@@ -85,7 +85,7 @@
// Retrieves an image specified by the URL, displays it in the UI.
ImageRequest request = new ImageRequest(url,
- new Response.Listener<Bitmap>() {
+ new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap bitmap) {
mImageView.setImageBitmap(bitmap);
@@ -257,7 +257,7 @@
String url = "http://my-json-feed";
JsonObjectRequest jsObjRequest = new JsonObjectRequest
- (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
+ (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
diff --git a/docs/html/training/volley/simple.jd b/docs/html/training/volley/simple.jd
index 942c57f..ecb5fde 100644
--- a/docs/html/training/volley/simple.jd
+++ b/docs/html/training/volley/simple.jd
@@ -63,7 +63,7 @@
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
- new Response.Listener<String>() {
+ new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk
index e05dd55..5dacbb5 100644
--- a/libs/hwui/Android.common.mk
+++ b/libs/hwui/Android.common.mk
@@ -43,11 +43,13 @@
Extensions.cpp \
FboCache.cpp \
FontRenderer.cpp \
+ FrameInfo.cpp \
GammaFontRenderer.cpp \
GlopBuilder.cpp \
GradientCache.cpp \
Image.cpp \
Interpolator.cpp \
+ JankTracker.cpp \
Layer.cpp \
LayerCache.cpp \
LayerRenderer.cpp \
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
index b3bd5fd..97dec88 100644
--- a/libs/hwui/FloatColor.h
+++ b/libs/hwui/FloatColor.h
@@ -31,6 +31,13 @@
b = a * ((color ) & 0xff) / 255.0f;
}
+ bool isNotBlack() {
+ return a < 1.0f
+ || r > 0.0f
+ || g > 0.0f
+ || b > 0.0f;
+ }
+
float r;
float g;
float b;
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
new file mode 100644
index 0000000..6da1fa8
--- /dev/null
+++ b/libs/hwui/FrameInfo.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "FrameInfo.h"
+
+#include <cstring>
+
+namespace android {
+namespace uirenderer {
+
+void FrameInfo::importUiThreadInfo(int64_t* info) {
+ memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
new file mode 100644
index 0000000..3c31677
--- /dev/null
+++ b/libs/hwui/FrameInfo.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef FRAMEINFO_H_
+#define FRAMEINFO_H_
+
+#include "utils/Macros.h"
+
+#include <cutils/compiler.h>
+#include <utils/Timers.h>
+
+#include <memory.h>
+
+namespace android {
+namespace uirenderer {
+
+#define UI_THREAD_FRAME_INFO_SIZE 9
+
+HWUI_ENUM(FrameInfoIndex,
+ kFlags = 0,
+ kIntendedVsync,
+ kVsync,
+ kOldestInputEvent,
+ kNewestInputEvent,
+ kHandleInputStart,
+ kAnimationStart,
+ kPerformTraversalsStart,
+ kDrawStart,
+ // End of UI frame info
+
+ kSyncStart,
+ kIssueDrawCommandsStart,
+ kSwapBuffers,
+ kFrameCompleted,
+
+ // Must be the last value!
+ kNumIndexes
+);
+
+HWUI_ENUM(FrameInfoFlags,
+ kWindowLayoutChanged = 1 << 0,
+ kRTAnimation = 1 << 1,
+ kSurfaceCanvas = 1 << 2,
+);
+
+class ANDROID_API UiFrameInfoBuilder {
+public:
+ UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
+ memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
+ }
+
+ UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
+ mBuffer[FrameInfoIndex::kVsync] = vsyncTime;
+ mBuffer[FrameInfoIndex::kIntendedVsync] = intendedVsync;
+ return *this;
+ }
+
+ UiFrameInfoBuilder& addFlag(FrameInfoFlagsEnum flag) {
+ mBuffer[FrameInfoIndex::kFlags] |= static_cast<uint64_t>(flag);
+ return *this;
+ }
+
+private:
+ int64_t* mBuffer;
+};
+
+class FrameInfo {
+public:
+ void importUiThreadInfo(int64_t* info);
+
+ void markSyncStart() {
+ mFrameInfo[FrameInfoIndex::kSyncStart] = systemTime(CLOCK_MONOTONIC);
+ }
+
+ void markIssueDrawCommandsStart() {
+ mFrameInfo[FrameInfoIndex::kIssueDrawCommandsStart] = systemTime(CLOCK_MONOTONIC);
+ }
+
+ void markSwapBuffers() {
+ mFrameInfo[FrameInfoIndex::kSwapBuffers] = systemTime(CLOCK_MONOTONIC);
+ }
+
+ void markFrameCompleted() {
+ mFrameInfo[FrameInfoIndex::kFrameCompleted] = systemTime(CLOCK_MONOTONIC);
+ }
+
+ int64_t operator[](FrameInfoIndexEnum index) const {
+ if (index == FrameInfoIndex::kNumIndexes) return 0;
+ return mFrameInfo[static_cast<int>(index)];
+ }
+
+ int64_t operator[](int index) const {
+ if (index < 0 || index >= FrameInfoIndex::kNumIndexes) return 0;
+ return mFrameInfo[static_cast<int>(index)];
+ }
+
+private:
+ int64_t mFrameInfo[FrameInfoIndex::kNumIndexes];
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* FRAMEINFO_H_ */
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index bdc5c5c2..f133d42 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -271,10 +271,7 @@
}
if (isAlphaMaskTexture) {
- mDescription.modulate = mOutGlop->fill.color.a < 1.0f
- || mOutGlop->fill.color.r > 0.0f
- || mOutGlop->fill.color.g > 0.0f
- || mOutGlop->fill.color.b > 0.0f;
+ mDescription.modulate = mOutGlop->fill.color.isNotBlack();
} else {
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
}
@@ -295,27 +292,74 @@
return *this;
}
-GlopBuilder& GlopBuilder::setFillPathTexturePaint(Texture& texture,
+GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
const SkPaint& paint, float alphaScale) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
mOutGlop->fill.texture = &texture;
- //specify invalid, since these are always static for path textures
+ //specify invalid, since these are always static for PathTextures
mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
paint.getShader(), paint.getColorFilter());
- mDescription.modulate = mOutGlop->fill.color.a < 1.0f
- || mOutGlop->fill.color.r > 0.0f
- || mOutGlop->fill.color.g > 0.0f
- || mOutGlop->fill.color.b > 0.0f;
+ mDescription.modulate = mOutGlop->fill.color.isNotBlack();
return *this;
}
+GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
+ const SkPaint& paint, float alphaScale) {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = &texture;
+
+ //specify invalid, since these are always static for ShadowTextures
+ mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
+ mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
+
+ const int ALPHA_BITMASK = SK_ColorBLACK;
+ const int COLOR_BITMASK = ~ALPHA_BITMASK;
+ if ((shadowColor & ALPHA_BITMASK) == ALPHA_BITMASK) {
+ // shadow color is fully opaque: override its alpha with that of paint
+ shadowColor &= paint.getColor() | COLOR_BITMASK;
+ }
+
+ setFill(shadowColor, alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
+ paint.getShader(), paint.getColorFilter());
+
+ mDescription.modulate = mOutGlop->fill.color.isNotBlack();
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setFillBlack() {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = nullptr;
+ mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
+ mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
+
+ setFill(SK_ColorBLACK, 1.0f, SkXfermode::kSrcOver_Mode, nullptr, nullptr);
+
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setFillClear() {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = nullptr;
+ mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
+ mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
+
+ setFill(SK_ColorBLACK, 1.0f, SkXfermode::kClear_Mode, nullptr, nullptr);
+
+ return *this;
+}
////////////////////////////////////////////////////////////////////////////////
// Transform
////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 657e642..546e6c5 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -46,8 +46,12 @@
GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale);
GlopBuilder& setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture,
const SkPaint* paint, float alphaScale);
- GlopBuilder& setFillPathTexturePaint(Texture& texture,
+ GlopBuilder& setFillPathTexturePaint(PathTexture& texture,
const SkPaint& paint, float alphaScale);
+ GlopBuilder& setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
+ const SkPaint& paint, float alphaScale);
+ GlopBuilder& setFillBlack();
+ GlopBuilder& setFillClear();
GlopBuilder& setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset);
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
new file mode 100644
index 0000000..62cb97c
--- /dev/null
+++ b/libs/hwui/JankTracker.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "JankTracker.h"
+
+#include <cstdio>
+#include <inttypes.h>
+
+namespace android {
+namespace uirenderer {
+
+static const char* JANK_TYPE_NAMES[] = {
+ "Missed Vsync",
+ "High input latency",
+ "Slow UI thread",
+ "Slow bitmap uploads",
+ "Slow draw",
+};
+
+struct Comparison {
+ FrameInfoIndexEnum start;
+ FrameInfoIndexEnum end;
+};
+
+static const Comparison COMPARISONS[] = {
+ {FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync},
+ {FrameInfoIndex::kOldestInputEvent, FrameInfoIndex::kVsync},
+ {FrameInfoIndex::kVsync, FrameInfoIndex::kSyncStart},
+ {FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart},
+ {FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kFrameCompleted},
+};
+
+// If the event exceeds 10 seconds throw it away, this isn't a jank event
+// it's an ANR and will be handled as such
+static const int64_t IGNORE_EXCEEDING = seconds_to_nanoseconds(10);
+
+/*
+ * Frames that are exempt from jank metrics.
+ * First-draw frames, for example, are expected to
+ * be slow, this is hidden from the user with window animations and
+ * other tricks
+ *
+ * Similarly, we don't track direct-drawing via Surface:lockHardwareCanvas()
+ * for now
+ *
+ * TODO: kSurfaceCanvas can negatively impact other drawing by using up
+ * time on the RenderThread, figure out how to attribute that as a jank-causer
+ */
+static const int64_t EXEMPT_FRAMES_FLAGS
+ = FrameInfoFlags::kWindowLayoutChanged
+ | FrameInfoFlags::kSurfaceCanvas;
+
+JankTracker::JankTracker(nsecs_t frameIntervalNanos) {
+ reset();
+ setFrameInterval(frameIntervalNanos);
+}
+
+void JankTracker::setFrameInterval(nsecs_t frameInterval) {
+ mFrameInterval = frameInterval;
+ mThresholds[kMissedVsync] = 1;
+ /*
+ * Due to interpolation and sample rate differences between the touch
+ * panel and the display (example, 85hz touch panel driving a 60hz display)
+ * we call high latency 1.5 * frameinterval
+ *
+ * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel
+ * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms
+ * Thus this must always be larger than frameInterval, or it will fail
+ */
+ mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval);
+
+ // Note that these do not add up to 1. This is intentional. It's to deal
+ // with variance in values, and should be sort of an upper-bound on what
+ // is reasonable to expect.
+ mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval);
+ mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval);
+ mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval);
+
+}
+
+void JankTracker::addFrame(const FrameInfo& frame) {
+ using namespace FrameInfoIndex;
+ mTotalFrameCount++;
+ // Fast-path for jank-free frames
+ int64_t totalDuration = frame[kFrameCompleted] - frame[kIntendedVsync];
+ if (CC_LIKELY(totalDuration < mFrameInterval)) {
+ return;
+ }
+
+ if (frame[kFlags] & EXEMPT_FRAMES_FLAGS) {
+ return;
+ }
+
+ mJankFrameCount++;
+
+ for (int i = 0; i < NUM_BUCKETS; i++) {
+ int64_t delta = frame[COMPARISONS[i].end] - frame[COMPARISONS[i].start];
+ if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
+ mBuckets[i].count++;
+ }
+ }
+}
+
+void JankTracker::dump(int fd) {
+ FILE* file = fdopen(fd, "a");
+ fprintf(file, "\nFrame stats:");
+ fprintf(file, "\n Total frames rendered: %u", mTotalFrameCount);
+ fprintf(file, "\n Janky frames: %u (%.2f%%)", mJankFrameCount,
+ (float) mJankFrameCount / (float) mTotalFrameCount * 100.0f);
+ for (int i = 0; i < NUM_BUCKETS; i++) {
+ fprintf(file, "\n Number %s: %u", JANK_TYPE_NAMES[i], mBuckets[i].count);
+ }
+ fprintf(file, "\n");
+ fflush(file);
+}
+
+void JankTracker::reset() {
+ memset(mBuckets, 0, sizeof(JankBucket) * NUM_BUCKETS);
+ mTotalFrameCount = 0;
+ mJankFrameCount = 0;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
new file mode 100644
index 0000000..aa554cd
--- /dev/null
+++ b/libs/hwui/JankTracker.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef JANKTRACKER_H_
+#define JANKTRACKER_H_
+
+#include "FrameInfo.h"
+#include "renderthread/TimeLord.h"
+#include "utils/RingBuffer.h"
+
+#include <memory>
+
+namespace android {
+namespace uirenderer {
+
+enum JankType {
+ kMissedVsync = 0,
+ kHighInputLatency,
+ kSlowUI,
+ kSlowSync,
+ kSlowRT,
+
+ // must be last
+ NUM_BUCKETS,
+};
+
+struct JankBucket {
+ // Number of frames that hit this bucket
+ uint32_t count;
+};
+
+// TODO: Replace DrawProfiler with this
+class JankTracker {
+public:
+ JankTracker(nsecs_t frameIntervalNanos);
+
+ void setFrameInterval(nsecs_t frameIntervalNanos);
+
+ void addFrame(const FrameInfo& frame);
+
+ void dump(int fd);
+ void reset();
+
+private:
+ JankBucket mBuckets[NUM_BUCKETS];
+ int64_t mThresholds[NUM_BUCKETS];
+
+ int64_t mFrameInterval;
+ uint32_t mTotalFrameCount;
+ uint32_t mJankFrameCount;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* JANKTRACKER_H_ */
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4761ab4..3f79cef 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1198,8 +1198,8 @@
}
void OpenGLRenderer::clearLayerRegions() {
- const size_t count = mLayers.size();
- if (count == 0) return;
+ const size_t quadCount = mLayers.size();
+ if (quadCount == 0) return;
if (!mState.currentlyIgnored()) {
EVENT_LOGD("clearLayerRegions");
@@ -1212,10 +1212,10 @@
// is likely different so we need to disable clipping here
bool scissorChanged = mRenderState.scissor().setEnabled(false);
- Vertex mesh[count * 4];
+ Vertex mesh[quadCount * 4];
Vertex* vertex = mesh;
- for (uint32_t i = 0; i < count; i++) {
+ for (uint32_t i = 0; i < quadCount; i++) {
const Rect& bounds = mLayers[i];
Vertex::set(vertex++, bounds.left, bounds.top);
@@ -1228,18 +1228,30 @@
// the same thing again
mLayers.clear();
- SkPaint clearPaint;
- clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshIndexedQuads(&mesh[0], quadCount)
+ .setFillClear()
+ .setTransformClip(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setModelViewOffsetRect(0, 0, currentSnapshot()->getClipRect())
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ } else {
+ SkPaint clearPaint;
+ clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
- setupDraw(false);
- setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
- setupDrawBlending(&clearPaint, true);
- setupDrawProgram();
- setupDrawPureColorUniforms();
- setupDrawModelView(kModelViewMode_Translate, false,
- 0.0f, 0.0f, 0.0f, 0.0f, true);
+ setupDraw(false);
+ setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
+ setupDrawBlending(&clearPaint, true);
+ setupDrawProgram();
+ setupDrawPureColorUniforms();
+ setupDrawModelView(kModelViewMode_Translate, false,
+ 0.0f, 0.0f, 0.0f, 0.0f, true);
- issueIndexedQuadDraw(&mesh[0], count);
+ issueIndexedQuadDraw(&mesh[0], quadCount);
+ }
if (scissorChanged) mRenderState.scissor().setEnabled(true);
} else {
@@ -1391,11 +1403,11 @@
}
void OpenGLRenderer::drawRectangleList(const RectangleList& rectangleList) {
- int count = rectangleList.getTransformedRectanglesCount();
- std::vector<Vertex> rectangleVertices(count * 4);
+ int quadCount = rectangleList.getTransformedRectanglesCount();
+ std::vector<Vertex> rectangleVertices(quadCount * 4);
Rect scissorBox = rectangleList.calculateBounds();
scissorBox.snapToPixelBoundaries();
- for (int i = 0; i < count; ++i) {
+ for (int i = 0; i < quadCount; ++i) {
const TransformedRectangle& tr(rectangleList.getTransformedRectangle(i));
const Matrix4& transform = tr.getTransform();
Rect bounds = tr.getBounds();
@@ -1420,6 +1432,19 @@
mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
scissorBox.getWidth(), scissorBox.getHeight());
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshIndexedQuads(&rectangleVertices[0], rectangleVertices.size() / 4)
+ .setFillBlack()
+ .setTransformClip(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setModelViewOffsetRect(0, 0, scissorBox)
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
const SkPaint* paint = nullptr;
setupDraw();
setupDrawNoTexture();
@@ -2654,17 +2679,30 @@
// NOTE: The drop shadow will not perform gamma correction
// if shader-based correction is enabled
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
- const ShadowTexture* shadow = mCaches.dropShadowCache.get(
+ ShadowTexture* texture = mCaches.dropShadowCache.get(
paint, text, bytesCount, count, textShadow.radius, positions);
// If the drop shadow exceeds the max texture size or couldn't be
// allocated, skip drawing
- if (!shadow) return;
- const AutoTexture autoCleanup(shadow);
+ if (!texture) return;
+ const AutoTexture autoCleanup(texture);
- const float sx = x - shadow->left + textShadow.dx;
- const float sy = y - shadow->top + textShadow.dy;
+ const float sx = x - texture->left + textShadow.dx;
+ const float sy = y - texture->top + textShadow.dy;
- const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * writableSnapshot()->alpha;
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshTexturedUnitQuad(nullptr, true)
+ .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
+ .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
+ const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * currentSnapshot()->alpha;
if (getShader(paint)) {
textShadow.color = SK_ColorWHITE;
}
@@ -2677,8 +2715,8 @@
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
- sx, sy, sx + shadow->width, sy + shadow->height);
- setupDrawTexture(shadow->id);
+ sx, sy, sx + texture->width, sy + texture->height);
+ setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms(getShader(paint));
@@ -3010,7 +3048,6 @@
DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
composeLayerRect(layer, layer->regionRect));
} else if (layer->mesh) {
-
const float a = getLayerAlpha(layer);
setupDraw();
setupDrawWithTexture();
@@ -3093,8 +3130,8 @@
return texture;
}
-void OpenGLRenderer::drawPathTexture(PathTexture* texture,
- float x, float y, const SkPaint* paint) {
+void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y,
+ const SkPaint* paint) {
if (quickRejectSetupScissor(x, y, x + texture->width, y + texture->height)) {
return;
}
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index de5f91c..3c65705 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -228,21 +228,23 @@
}
// setup the first glyph position and adjust bounds if needed
+ int xBaseline = 0;
+ int yBaseline = 0;
if (mCanvas->drawTextAbsolutePos()) {
bounds.offset(x,y);
- pointStorage[0].set(x, y);
- } else {
- pointStorage[0].set(0, 0);
+ xBaseline = x;
+ yBaseline = y;
}
+ pointStorage[0].set(xBaseline, yBaseline);
// setup the remaining glyph positions
if (glyphs.paint.isVerticalText()) {
for (int i = 1; i < glyphs.count; i++) {
- pointStorage[i].set(x, glyphWidths[i-1] + pointStorage[i-1].fY);
+ pointStorage[i].set(xBaseline, glyphWidths[i-1] + pointStorage[i-1].fY);
}
} else {
for (int i = 1; i < glyphs.count; i++) {
- pointStorage[i].set(glyphWidths[i-1] + pointStorage[i-1].fX, y);
+ pointStorage[i].set(glyphWidths[i-1] + pointStorage[i-1].fX, yBaseline);
}
}
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 81531e8..2fcf7f3 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -685,7 +685,7 @@
}
description->hasBitmap = true;
-
+ outData->layer = layer;
outData->bitmapSampler = (*textureUnit)++;
const float width = layer->getWidth();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 6346479..80c60d9 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -48,7 +48,8 @@
, mCanvas(nullptr)
, mHaveNewSurface(false)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mRootRenderNode(rootRenderNode) {
+ , mRootRenderNode(rootRenderNode)
+ , mCurrentFrameInfo(nullptr) {
mRenderThread.renderState().registerCanvasContext(this);
}
@@ -151,9 +152,13 @@
}
}
-void CanvasContext::prepareTree(TreeInfo& info) {
+void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) {
mRenderThread.removeFrameCallback(this);
+ mCurrentFrameInfo = &mFrames.next();
+ mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
+ mCurrentFrameInfo->markSyncStart();
+
info.damageAccumulator = &mDamageAccumulator;
info.renderer = mCanvas;
if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
@@ -203,6 +208,7 @@
"drawRenderNode called on a context with no canvas or surface!");
profiler().markPlaybackStart();
+ mCurrentFrameInfo->markIssueDrawCommandsStart();
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -239,12 +245,19 @@
profiler().markPlaybackEnd();
+ // Even if we decided to cancel the frame, from the perspective of jank
+ // metrics the frame was swapped at this point
+ mCurrentFrameInfo->markSwapBuffers();
+
if (drew) {
swapBuffers();
} else {
mEglManager.cancelFrame();
}
+ // TODO: Use a fence for real completion?
+ mCurrentFrameInfo->markFrameCompleted();
+ mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
profiler().finishFrame();
}
@@ -257,9 +270,14 @@
ATRACE_CALL();
profiler().startFrame();
+ int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
+ UiFrameInfoBuilder(frameInfo)
+ .addFlag(FrameInfoFlags::kRTAnimation)
+ .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(),
+ mRenderThread.timeLord().latestVsync());
TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
- prepareTree(info);
+ prepareTree(info, frameInfo);
if (info.out.canDrawThisFrame) {
draw();
}
@@ -372,6 +390,28 @@
thread.eglManager().setTextureAtlas(buffer, map, mapSize);
}
+void CanvasContext::dumpFrames(int fd) {
+ FILE* file = fdopen(fd, "a");
+ fprintf(file, "\n\n---PROFILEDATA---");
+ for (size_t i = 0; i < mFrames.size(); i++) {
+ FrameInfo& frame = mFrames[i];
+ if (frame[FrameInfoIndex::kSyncStart] == 0) {
+ continue;
+ }
+ fprintf(file, "\n");
+ for (int i = 0; i < FrameInfoIndex::kNumIndexes; i++) {
+ fprintf(file, "%" PRId64 ",", frame[i]);
+ }
+ }
+ fprintf(file, "\n---PROFILEDATA---\n\n");
+ fflush(file);
+}
+
+void CanvasContext::resetFrameStats() {
+ mFrames.clear();
+ mRenderThread.jankTracker().reset();
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d3fbde8..9a60dc7 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -17,7 +17,14 @@
#ifndef CANVASCONTEXT_H_
#define CANVASCONTEXT_H_
-#include <set>
+#include "DamageAccumulator.h"
+#include "DrawProfiler.h"
+#include "IContextFactory.h"
+#include "FrameInfo.h"
+#include "RenderNode.h"
+#include "utils/RingBuffer.h"
+#include "renderthread/RenderTask.h"
+#include "renderthread/RenderThread.h"
#include <cutils/compiler.h>
#include <EGL/egl.h>
@@ -25,14 +32,7 @@
#include <utils/Functor.h>
#include <utils/Vector.h>
-#include "../DamageAccumulator.h"
-#include "../DrawProfiler.h"
-#include "../IContextFactory.h"
-#include "../RenderNode.h"
-#include "RenderTask.h"
-#include "RenderThread.h"
-
-#define FUNCTOR_PROCESS_DELAY 4
+#include <set>
namespace android {
namespace uirenderer {
@@ -75,7 +75,7 @@
void setOpaque(bool opaque);
void makeCurrent();
void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
- void prepareTree(TreeInfo& info);
+ void prepareTree(TreeInfo& info, int64_t* uiFrameInfo);
void draw();
void destroy();
@@ -103,6 +103,9 @@
DrawProfiler& profiler() { return mProfiler; }
+ void dumpFrames(int fd);
+ void resetFrameStats();
+
private:
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
@@ -133,6 +136,9 @@
const sp<RenderNode> mRootRenderNode;
DrawProfiler mProfiler;
+ FrameInfo* mCurrentFrameInfo;
+ // Ring buffer large enough for 1 second worth of frames
+ RingBuffer<FrameInfo, 60> mFrames;
std::set<RenderNode*> mPrefetechedLayers;
};
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 4d8a469..679a00f 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -34,8 +34,6 @@
DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
- , mFrameTimeNanos(0)
- , mRecordDurationNanos(0)
, mDensity(1.0f) // safe enough default
, mSyncResult(kSync_OK) {
}
@@ -68,18 +66,12 @@
}
}
-int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos) {
+int DrawFrameTask::drawFrame() {
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
mSyncResult = kSync_OK;
- mFrameTimeNanos = frameTimeNanos;
- mRecordDurationNanos = recordDurationNanos;
postAndWait();
- // Reset the single-frame data
- mFrameTimeNanos = 0;
- mRecordDurationNanos = 0;
-
return mSyncResult;
}
@@ -93,7 +85,7 @@
ATRACE_NAME("DrawFrame");
mContext->profiler().setDensity(mDensity);
- mContext->profiler().startFrame(mRecordDurationNanos);
+ mContext->profiler().startFrame();
bool canUnblockUiThread;
bool canDrawThisFrame;
@@ -122,7 +114,7 @@
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
- mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
+ mRenderThread->timeLord().vsyncReceived(mFrameInfo[FrameInfoIndex::kVsync]);
mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse();
@@ -130,7 +122,7 @@
mContext->processLayerUpdate(mLayers[i].get());
}
mLayers.clear();
- mContext->prepareTree(info);
+ mContext->prepareTree(info, mFrameInfo);
// This is after the prepareTree so that any pending operations
// (RenderNode tree state, prefetched layers, etc...) will be flushed.
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 953f012..0e56bea 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -25,6 +25,7 @@
#include "RenderTask.h"
#include "../Rect.h"
+#include "../FrameInfo.h"
#include "../TreeInfo.h"
namespace android {
@@ -62,7 +63,9 @@
void removeLayerUpdate(DeferredLayerUpdater* layer);
void setDensity(float density) { mDensity = density; }
- int drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos);
+ int drawFrame();
+
+ int64_t* frameInfo() { return mFrameInfo; }
virtual void run() override;
@@ -80,12 +83,12 @@
/*********************************************
* Single frame data
*********************************************/
- nsecs_t mFrameTimeNanos;
- nsecs_t mRecordDurationNanos;
float mDensity;
std::vector< sp<DeferredLayerUpdater> > mLayers;
int mSyncResult;
+
+ int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 4dc4248..3a31db0 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -16,14 +16,14 @@
#include "RenderProxy.h"
-#include "CanvasContext.h"
-#include "RenderTask.h"
-#include "RenderThread.h"
-
-#include "../DeferredLayerUpdater.h"
-#include "../DisplayList.h"
-#include "../LayerRenderer.h"
-#include "../Rect.h"
+#include "DeferredLayerUpdater.h"
+#include "DisplayList.h"
+#include "LayerRenderer.h"
+#include "Rect.h"
+#include "renderthread/CanvasContext.h"
+#include "renderthread/RenderTask.h"
+#include "renderthread/RenderThread.h"
+#include "utils/Macros.h"
namespace android {
namespace uirenderer {
@@ -52,6 +52,11 @@
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
+HWUI_ENUM(DumpFlags,
+ kFrameStats = 1 << 0,
+ kReset = 1 << 1,
+);
+
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
return new CanvasContext(*args->thread, args->translucent,
@@ -92,7 +97,7 @@
}
CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) {
- args->thread->timeLord().setFrameInterval(args->frameIntervalNanos);
+ args->thread->setFrameInterval(args->frameIntervalNanos);
return nullptr;
}
@@ -175,7 +180,8 @@
}
void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+ uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density) {
+ mDrawFrameTask.setDensity(density);
SETUP_TASK(setup);
args->context = mContext;
args->width = width;
@@ -199,10 +205,12 @@
post(task);
}
-int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
- float density) {
- mDrawFrameTask.setDensity(density);
- return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
+int64_t* RenderProxy::frameInfo() {
+ return mDrawFrameTask.frameInfo();
+}
+
+int RenderProxy::syncAndDrawFrame() {
+ return mDrawFrameTask.drawFrame();
}
CREATE_BRIDGE1(destroy, CanvasContext* context) {
@@ -375,19 +383,28 @@
mRenderThread.queueAtFront(task);
}
-CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) {
+CREATE_BRIDGE3(dumpProfileInfo, CanvasContext* context, int fd, int dumpFlags) {
args->context->profiler().dumpData(args->fd);
+ if (args->dumpFlags & DumpFlags::kFrameStats) {
+ args->context->dumpFrames(args->fd);
+ }
+ if (args->dumpFlags & DumpFlags::kReset) {
+ args->context->resetFrameStats();
+ }
return nullptr;
}
-void RenderProxy::dumpProfileInfo(int fd) {
+void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
SETUP_TASK(dumpProfileInfo);
args->context = mContext;
args->fd = fd;
+ args->dumpFlags = dumpFlags;
postAndWait(task);
}
-CREATE_BRIDGE1(dumpGraphicsMemory, int fd) {
+CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
+ args->thread->jankTracker().dump(args->fd);
+
FILE *file = fdopen(args->fd, "a");
if (Caches::hasInstance()) {
String8 cachesLog;
@@ -403,6 +420,7 @@
void RenderProxy::dumpGraphicsMemory(int fd) {
SETUP_TASK(dumpGraphicsMemory);
args->fd = fd;
+ args->thread = &RenderThread::getInstance();
staticPostAndWait(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d87e777..19e73e5 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -71,10 +71,10 @@
ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density);
ANDROID_API void setOpaque(bool opaque);
- ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
- float density);
+ ANDROID_API int64_t* frameInfo();
+ ANDROID_API int syncAndDrawFrame();
ANDROID_API void destroy();
ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
@@ -95,7 +95,7 @@
ANDROID_API void stopDrawing();
ANDROID_API void notifyFramePending();
- ANDROID_API void dumpProfileInfo(int fd);
+ ANDROID_API void dumpProfileInfo(int fd, int dumpFlags);
ANDROID_API static void dumpGraphicsMemory(int fd);
ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 9a0fbad..2a8baa7 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -151,6 +151,11 @@
LOG_ALWAYS_FATAL("Can't destroy the render thread");
}
+void RenderThread::setFrameInterval(nsecs_t frameInterval) {
+ mTimeLord.setFrameInterval(frameInterval);
+ mJankTracker->setFrameInterval(frameInterval);
+}
+
void RenderThread::initializeDisplayEventReceiver() {
LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
mDisplayEventReceiver = new DisplayEventReceiver();
@@ -167,6 +172,7 @@
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
mRenderState = new RenderState(*this);
+ mJankTracker = new JankTracker(mTimeLord.frameIntervalNanos());
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 8fc8ca5..f169424 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -19,8 +19,8 @@
#include "RenderTask.h"
-#include <memory>
-#include <set>
+#include "../JankTracker.h"
+#include "TimeLord.h"
#include <cutils/compiler.h>
#include <utils/Looper.h>
@@ -28,7 +28,8 @@
#include <utils/Singleton.h>
#include <utils/Thread.h>
-#include "TimeLord.h"
+#include <memory>
+#include <set>
namespace android {
@@ -85,9 +86,12 @@
// the next vsync. If it is not currently registered this does nothing.
void pushBackFrameCallback(IFrameCallback* callback);
+ void setFrameInterval(nsecs_t frameInterval);
+
TimeLord& timeLord() { return mTimeLord; }
RenderState& renderState() { return *mRenderState; }
EglManager& eglManager() { return *mEglManager; }
+ JankTracker& jankTracker() { return *mJankTracker; }
protected:
virtual bool threadLoop() override;
@@ -132,6 +136,8 @@
TimeLord mTimeLord;
RenderState* mRenderState;
EglManager* mEglManager;
+
+ JankTracker* mJankTracker = nullptr;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index f187493..f846d6a 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -32,7 +32,7 @@
return false;
}
-nsecs_t TimeLord::computeFrameTimeMs() {
+nsecs_t TimeLord::computeFrameTimeNanos() {
// Logic copied from Choreographer.java
nsecs_t now = systemTime(CLOCK_MONOTONIC);
nsecs_t jitterNanos = now - mFrameTimeNanos;
@@ -40,7 +40,11 @@
nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
mFrameTimeNanos = now - lastFrameOffset;
}
- return nanoseconds_to_milliseconds(mFrameTimeNanos);
+ return mFrameTimeNanos;
+}
+
+nsecs_t TimeLord::computeFrameTimeMs() {
+ return nanoseconds_to_milliseconds(computeFrameTimeNanos());
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 7c155d2..5464399 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -29,9 +29,13 @@
class TimeLord {
public:
void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; }
+ nsecs_t frameIntervalNanos() const { return mFrameIntervalNanos; }
+
// returns true if the vsync is newer, false if it was rejected for staleness
bool vsyncReceived(nsecs_t vsync);
+ nsecs_t latestVsync() { return mFrameTimeNanos; }
nsecs_t computeFrameTimeMs();
+ nsecs_t computeFrameTimeNanos();
private:
friend class RenderThread;
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index b6d2c4d..0431e22 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -85,7 +85,7 @@
proxy->initialize(surface);
float lightX = width / 2.0;
proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)},
- dp(800.0f), 255 * 0.075, 255 * 0.15);
+ dp(800.0f), 255 * 0.075, 255 * 0.15, gDisplay.density);
android::uirenderer::Rect DUMMY;
@@ -100,8 +100,7 @@
ATRACE_NAME("UI-Draw Frame");
animation.doFrame(i);
- nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
- proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density);
+ proxy->syncAndDrawFrame();
}
sleep(5);
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index 5ca9083..b93f720 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -35,4 +35,12 @@
static_assert(std::is_standard_layout<Type>::value, \
#Type " must have standard layout")
+#define HWUI_ENUM(name, ...) \
+ namespace name { \
+ enum _##name { \
+ __VA_ARGS__ \
+ }; \
+ } \
+ typedef enum name::_##name name##Enum
+
#endif /* MACROS_H */
diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h
new file mode 100644
index 0000000..fc9aec0
--- /dev/null
+++ b/libs/hwui/utils/RingBuffer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef RINGBUFFER_H_
+#define RINGBUFFER_H_
+
+#include "utils/Macros.h"
+
+#include <stddef.h>
+
+namespace android {
+namespace uirenderer {
+
+template<class T, size_t SIZE>
+class RingBuffer {
+ PREVENT_COPY_AND_ASSIGN(RingBuffer);
+
+public:
+ RingBuffer() {}
+ ~RingBuffer() {}
+
+ size_t capacity() { return SIZE; }
+ size_t size() { return mCount; }
+
+ T& next() {
+ mHead = (mHead + 1) % SIZE;
+ if (mCount < SIZE) {
+ mCount++;
+ }
+ return mBuffer[mHead];
+ }
+
+ T& front() {
+ return this[0];
+ }
+
+ T& back() {
+ return this[size() - 1];
+ }
+
+ T& operator[](size_t index) {
+ return mBuffer[(mHead + index + 1) % mCount];
+ }
+
+ void clear() {
+ mCount = 0;
+ mHead = -1;
+ }
+
+private:
+ T mBuffer[SIZE];
+ int mHead = -1;
+ size_t mCount = 0;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif /* RINGBUFFER_H_ */
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index ca242e4..97919a9 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -209,8 +209,23 @@
@SystemApi
public final static int FLAG_HW_HOTWORD = 0x1 << 5;
+ /**
+ * @hide
+ * Flag requesting audible playback even under limited interruptions.
+ */
+ @SystemApi
+ public final static int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1 << 6;
+
+ /**
+ * @hide
+ * Flag requesting audible playback even when the underlying stream is muted.
+ */
+ @SystemApi
+ public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
+
private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
- FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD;
+ FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
+ FLAG_BYPASS_MUTE;
private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC;
private int mUsage = USAGE_UNKNOWN;
diff --git a/media/java/android/media/AudioDevicesManager.java b/media/java/android/media/AudioDevicesManager.java
new file mode 100644
index 0000000..bce2100
--- /dev/null
+++ b/media/java/android/media/AudioDevicesManager.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.content.Context;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import android.content.Context;
+
+/** @hide
+ * API candidate
+ */
+public class AudioDevicesManager {
+ private static String TAG = "AudioDevicesManager";
+ private static boolean DEBUG = true;
+
+ private AudioManager mAudioManager = null;
+ private OnAmPortUpdateListener mPortListener = null;
+
+ /*
+ * Enum/Selection API
+ */
+ public AudioDevicesManager(Context context) {
+ mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+ mPortListener = new OnAmPortUpdateListener();
+ mAudioManager.registerAudioPortUpdateListener(mPortListener);
+ }
+
+ /** @hide
+ * API candidate
+ */
+ //TODO Merge this class into android.media.AudioDevice
+ public class AudioDeviceInfo {
+ private AudioDevicePort mPort = null;
+
+ /** @hide */
+ /* package */ AudioDeviceInfo(AudioDevicePort port) {
+ mPort = port;
+ }
+
+ public int getId() { return mPort.handle().id(); }
+
+ public String getName() { return mPort.name(); }
+
+ public int getType() {
+ return mPort.type();
+ }
+
+ public String getAddress() {
+ return mPort.address();
+ }
+
+ public int getRole() { return mPort.role(); }
+
+ public int[] getSampleRates() { return mPort.samplingRates(); }
+
+ public int[] getChannelMasks() { return mPort.channelMasks(); }
+
+ public int[] getChannelCounts() {
+ int[] masks = getChannelMasks();
+ int[] counts = new int[masks.length];
+ for (int mask_index = 0; mask_index < masks.length; mask_index++) {
+ counts[mask_index] = getRole() == AudioPort.ROLE_SINK
+ ? AudioFormat.channelCountFromOutChannelMask(masks[mask_index])
+ : AudioFormat.channelCountFromInChannelMask(masks[mask_index]);
+ }
+ return counts;
+ }
+
+ /* The format IDs are in AudioFormat.java */
+ public int[] getFormats() { return mPort.formats(); }
+
+ public String toString() { return "" + getId() + " - " + getName(); }
+ }
+
+ /** @hide */
+ public static final int LIST_DEVICES_OUTPUTS = 0x0001;
+ /** @hide */
+ public static final int LIST_DEVICES_INPUTS = 0x0002;
+ /** @hide */
+ public static final int LIST_DEVICES_BUILTIN = 0x0004;
+ /** @hide */
+ public static final int LIST_DEVICES_USB = 0x0008;
+ // TODO implement the semantics for these.
+ /** @hide */
+ public static final int LIST_DEVICES_WIRED = 0x0010;
+ /** @hide */
+ public static final int LIST_DEVICES_UNWIRED = 0x0020;
+
+ /** @hide */
+ public static final int LIST_DEVICES_ALL = LIST_DEVICES_OUTPUTS | LIST_DEVICES_INPUTS;
+
+ private boolean checkFlags(AudioDevicePort port, int flags) {
+ // Inputs / Outputs
+ boolean passed =
+ port.role() == AudioPort.ROLE_SINK && (flags & LIST_DEVICES_OUTPUTS) != 0 ||
+ port.role() == AudioPort.ROLE_SOURCE && (flags & LIST_DEVICES_INPUTS) != 0;
+
+ // USB
+ if (passed && (flags & LIST_DEVICES_USB) != 0) {
+ int role = port.role();
+ int type = port.type();
+ Slog.i(TAG, " role:" + role + " type:0x" + Integer.toHexString(type));
+ passed =
+ (role == AudioPort.ROLE_SINK && (type & AudioSystem.DEVICE_OUT_ALL_USB) != 0) ||
+ (role == AudioPort.ROLE_SOURCE && (type & AudioSystem.DEVICE_IN_ALL_USB) != 0);
+ }
+
+ return passed;
+ }
+
+ /** @hide */
+ public ArrayList<AudioDeviceInfo> listDevices(int flags) {
+ Slog.i(TAG, "AudioManager.listDevices(" + Integer.toHexString(flags) + ")");
+
+ ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>();
+ int status = mAudioManager.listAudioDevicePorts(ports);
+
+ Slog.i(TAG, " status:" + status + " numPorts:" + ports.size());
+
+ ArrayList<AudioDeviceInfo> deviceList = new ArrayList<AudioDeviceInfo>();
+
+ if (status == AudioManager.SUCCESS) {
+ deviceList = new ArrayList<AudioDeviceInfo>();
+ for (AudioDevicePort port : ports) {
+ if (checkFlags(port, flags)) {
+ deviceList.add(new AudioDeviceInfo(port));
+ }
+ }
+ }
+ return deviceList;
+ }
+
+ private ArrayList<OnAudioDeviceConnectionListener> mDeviceConnectionListeners =
+ new ArrayList<OnAudioDeviceConnectionListener>();
+
+ private HashMap<Integer, AudioPort> mCurrentPortlist =
+ new HashMap<Integer, AudioPort>();
+
+ private ArrayList<AudioDeviceInfo> calcAddedDevices(AudioPort[] portList) {
+ ArrayList<AudioDeviceInfo> addedDevices = new ArrayList<AudioDeviceInfo>();
+ synchronized(mCurrentPortlist) {
+ for(int portIndex = 0; portIndex < portList.length; portIndex++) {
+ if (portList[portIndex] instanceof AudioDevicePort) {
+ if (!mCurrentPortlist.containsKey(portList[portIndex].handle().id())) {
+ addedDevices.add(new AudioDeviceInfo((AudioDevicePort)portList[portIndex]));
+ }
+ }
+ }
+ }
+ return addedDevices;
+ }
+
+ private boolean hasPortId(AudioPort[] portList, int id) {
+ for(int portIndex = 0; portIndex < portList.length; portIndex++) {
+ if (portList[portIndex].handle().id() == id) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ArrayList<AudioDeviceInfo> calcRemovedDevices(AudioPort[] portList) {
+ ArrayList<AudioDeviceInfo> removedDevices = new ArrayList<AudioDeviceInfo>();
+
+ synchronized (mCurrentPortlist) {
+ Iterator it = mCurrentPortlist.entrySet().iterator();
+ while (it.hasNext()) {
+ HashMap.Entry pairs = (HashMap.Entry)it.next();
+ if (pairs.getValue() instanceof AudioDevicePort) {
+ if (!hasPortId(portList, ((Integer)pairs.getKey()).intValue())) {
+ removedDevices.add(new AudioDeviceInfo((AudioDevicePort)pairs.getValue()));
+ }
+ }
+ }
+ }
+ return removedDevices;
+ }
+
+ private void buildCurrentDevicesList(AudioPort[] portList) {
+ synchronized (mCurrentPortlist) {
+ mCurrentPortlist.clear();
+ for (int portIndex = 0; portIndex < portList.length; portIndex++) {
+ if (portList[portIndex] instanceof AudioDevicePort) {
+ mCurrentPortlist.put(portList[portIndex].handle().id(),
+ (AudioDevicePort)portList[portIndex]);
+ }
+ }
+ }
+ }
+
+ /** @hide */
+ public void addDeviceConnectionListener(OnAudioDeviceConnectionListener listener) {
+ synchronized (mDeviceConnectionListeners) {
+ mDeviceConnectionListeners.add(listener);
+ }
+ }
+
+ /** @hide */
+ public void removeDeviceConnectionListener(OnAudioDeviceConnectionListener listener) {
+ synchronized (mDeviceConnectionListeners) {
+ mDeviceConnectionListeners.remove(listener);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ private class OnAmPortUpdateListener implements AudioManager.OnAudioPortUpdateListener {
+ static final String TAG = "OnAmPortUpdateListener";
+ public void onAudioPortListUpdate(AudioPort[] portList) {
+ Slog.i(TAG, "onAudioPortListUpdate() " + portList.length + " ports.");
+ ArrayList<AudioDeviceInfo> addedDevices = calcAddedDevices(portList);
+ ArrayList<AudioDeviceInfo> removedDevices = calcRemovedDevices(portList);
+
+ ArrayList<OnAudioDeviceConnectionListener> listeners = null;
+ synchronized (mDeviceConnectionListeners) {
+ listeners =
+ new ArrayList<OnAudioDeviceConnectionListener>(mDeviceConnectionListeners);
+ }
+
+ // Connect
+ if (addedDevices.size() != 0) {
+ for (OnAudioDeviceConnectionListener listener : listeners) {
+ listener.onConnect(addedDevices);
+ }
+ }
+
+ // Disconnect?
+ if (removedDevices.size() != 0) {
+ for (OnAudioDeviceConnectionListener listener : listeners) {
+ listener.onDisconnect(removedDevices);
+ }
+ }
+
+ buildCurrentDevicesList(portList);
+ }
+
+ /**
+ * Callback method called upon audio patch list update.
+ * @param patchList the updated list of audio patches
+ */
+ public void onAudioPatchListUpdate(AudioPatch[] patchList) {
+ Slog.i(TAG, "onAudioPatchListUpdate() " + patchList.length + " patches.");
+ }
+
+ /**
+ * Callback method called when the mediaserver dies
+ */
+ public void onServiceDied() {
+ Slog.i(TAG, "onServiceDied()");
+ }
+ }
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index da89cf4..9876995 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3459,14 +3459,14 @@
* @see listAudioPorts(ArrayList<AudioPort>)
* @hide
*/
- public int listAudioDevicePorts(ArrayList<AudioPort> devices) {
+ public int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
int status = updateAudioPortCache(ports, null);
if (status == SUCCESS) {
devices.clear();
for (int i = 0; i < ports.size(); i++) {
if (ports.get(i) instanceof AudioDevicePort) {
- devices.add(ports.get(i));
+ devices.add((AudioDevicePort)ports.get(i));
}
}
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index caccb6e..cd78234 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1178,6 +1178,9 @@
}
private boolean isRestricted() {
+ if ((mAttributes.getFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
+ return false;
+ }
try {
final int usage = AudioAttributes.usageForLegacyStreamType(mStreamType);
final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, usage,
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 615dac2..fc372eb 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -604,6 +604,7 @@
private final IAppOpsService mAppOps;
private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
private int mUsage = -1;
+ private boolean mBypassInterruptionPolicy;
/**
* Default constructor. Consider using one of the create() methods for
@@ -1169,6 +1170,9 @@
private native void _start() throws IllegalStateException;
private boolean isRestricted() {
+ if (mBypassInterruptionPolicy) {
+ return false;
+ }
try {
final int usage = mUsage != -1 ? mUsage
: AudioAttributes.usageForLegacyStreamType(getAudioStreamType());
@@ -1560,6 +1564,8 @@
throw new IllegalArgumentException(msg);
}
mUsage = attributes.getUsage();
+ mBypassInterruptionPolicy = (attributes.getFlags()
+ & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0;
Parcel pattributes = Parcel.obtain();
attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS);
setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 5285074..b4c612a 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -17,6 +17,7 @@
package android.media;
import android.Manifest;
+import android.annotation.DrawableRes;
import android.app.ActivityThread;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -2083,7 +2084,7 @@
*
* @param resId Resource ID of an icon drawable to use to represent this route
*/
- public void setIconResource(int resId) {
+ public void setIconResource(@DrawableRes int resId) {
setIconDrawable(sStatic.mResources.getDrawable(resId));
}
@@ -2393,7 +2394,7 @@
*
* @param resId Resource ID of an icon drawable to use to represent this group
*/
- public void setIconResource(int resId) {
+ public void setIconResource(@DrawableRes int resId) {
setIconDrawable(sStatic.mResources.getDrawable(resId));
}
diff --git a/media/java/android/media/OnAudioDeviceConnectionListener.java b/media/java/android/media/OnAudioDeviceConnectionListener.java
new file mode 100644
index 0000000..4bdd4d0
--- /dev/null
+++ b/media/java/android/media/OnAudioDeviceConnectionListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import java.util.ArrayList;
+
+/**
+ * @hide
+ * API candidate
+ */
+public abstract class OnAudioDeviceConnectionListener {
+ public void onConnect(ArrayList<AudioDevicesManager.AudioDeviceInfo> devices) {}
+ public void onDisconnect(ArrayList<AudioDevicesManager.AudioDeviceInfo> devices) {}
+}
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 32d5b82..db6b38b 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -608,6 +608,9 @@
int priority, int loop, float rate);
private boolean isRestricted() {
+ if ((mAttributes.getFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
+ return false;
+ }
try {
final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
mAttributes.getUsage(),
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 5406130..cf69b8f 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -430,7 +430,7 @@
pData = buffer->data;
dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
break;
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
// Single plane 16bpp bayer data.
bytesPerPixel = 2;
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
@@ -517,7 +517,7 @@
pixelStride = 0;
break;
case HAL_PIXEL_FORMAT_Y16:
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
case HAL_PIXEL_FORMAT_RGB_565:
// Single plane 16bpp data.
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
@@ -584,7 +584,7 @@
rowStride = buffer->stride;
break;
case HAL_PIXEL_FORMAT_Y16:
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
// In native side, strides are specified in pixels, not in bytes.
// Single plane 16bpp bayer data. even width/height,
// row stride multiple of 16 pixels (32 bytes)
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index cff2fc7..7dcaf6d 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -64,6 +64,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:src="@drawable/ic_lockscreen_ime"
+ android:contentDescription="@string/accessibility_ime_switch_button"
android:clickable="true"
android:padding="8dip"
android:layout_gravity="end|center_vertical"
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 8b18b2ed..5047330 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -297,4 +297,7 @@
This is displayed if the phone is not connected to a carrier.-->
<string name="keyguard_carrier_default">No service.</string>
+ <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">Switch input method button.</string>
+
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 8371117..eac83d8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -32,14 +32,18 @@
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
+import com.android.internal.widget.LockPatternUtils;
+
import libcore.io.IoUtils;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.DataInputStream;
@@ -76,10 +80,11 @@
private static final String KEY_SECURE = "secure";
private static final String KEY_GLOBAL = "global";
private static final String KEY_LOCALE = "locale";
+ private static final String KEY_LOCK_SETTINGS = "lock_settings";
// Versioning of the state file. Increment this version
// number any time the set of state items is altered.
- private static final int STATE_VERSION = 3;
+ private static final int STATE_VERSION = 4;
// Slots in the checksum array. Never insert new items in the middle
// of this array; new slots must be appended.
@@ -89,20 +94,23 @@
private static final int STATE_WIFI_SUPPLICANT = 3;
private static final int STATE_WIFI_CONFIG = 4;
private static final int STATE_GLOBAL = 5;
+ private static final int STATE_LOCK_SETTINGS = 6;
- private static final int STATE_SIZE = 6; // The current number of state items
+ private static final int STATE_SIZE = 7; // The current number of state items
// Number of entries in the checksum array at various version numbers
private static final int STATE_SIZES[] = {
0,
4, // version 1
5, // version 2 added STATE_WIFI_CONFIG
- STATE_SIZE // version 3 added STATE_GLOBAL
+ 6, // version 3 added STATE_GLOBAL
+ STATE_SIZE // version 4 added STATE_LOCK_SETTINGS
};
// Versioning of the 'full backup' format
- private static final int FULL_BACKUP_VERSION = 2;
+ private static final int FULL_BACKUP_VERSION = 3;
private static final int FULL_BACKUP_ADDED_GLOBAL = 2; // added the "global" entry
+ private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry
private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
@@ -124,6 +132,10 @@
private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI";
private static final String KEY_WIFI_CONFIG = "\uffedCONFIG_WIFI";
+ // Keys within the lock settings section
+ private static final String KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED = "owner_info_enabled";
+ private static final String KEY_LOCK_SETTINGS_OWNER_INFO = "owner_info";
+
// Name of the temporary file we use during full backup/restore. This is
// stored in the full-backup tarfile as well, so should not be changed.
private static final String STAGE_FILE = "flattened-data";
@@ -367,6 +379,7 @@
byte[] systemSettingsData = getSystemSettings();
byte[] secureSettingsData = getSecureSettings();
byte[] globalSettingsData = getGlobalSettings();
+ byte[] lockSettingsData = getLockSettings();
byte[] locale = mSettingsHelper.getLocaleData();
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
@@ -387,6 +400,9 @@
stateChecksums[STATE_WIFI_CONFIG] =
writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
data);
+ stateChecksums[STATE_LOCK_SETTINGS] =
+ writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
+ lockSettingsData, data);
writeNewChecksums(stateChecksums, newState);
}
@@ -492,6 +508,8 @@
} else if (KEY_WIFI_CONFIG.equals(key)) {
initWifiRestoreIfNecessary();
mWifiRestore.incorporateWifiConfigFile(data);
+ } else if (KEY_LOCK_SETTINGS.equals(key)) {
+ restoreLockSettings(data);
} else {
data.skipEntityData();
}
@@ -513,6 +531,7 @@
byte[] systemSettingsData = getSystemSettings();
byte[] secureSettingsData = getSecureSettings();
byte[] globalSettingsData = getGlobalSettings();
+ byte[] lockSettingsData = getLockSettings();
byte[] locale = mSettingsHelper.getLocaleData();
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
@@ -547,6 +566,9 @@
if (DEBUG_BACKUP) Log.d(TAG, wifiConfigData.length + " bytes of wifi config data");
out.writeInt(wifiConfigData.length);
out.write(wifiConfigData);
+ if (DEBUG_BACKUP) Log.d(TAG, lockSettingsData.length + " bytes of lock settings data");
+ out.writeInt(lockSettingsData.length);
+ out.write(lockSettingsData);
out.flush(); // also flushes downstream
@@ -629,6 +651,16 @@
in.readFully(buffer, 0, nBytes);
restoreFileData(mWifiConfigFile, buffer, nBytes);
+ if (version >= FULL_BACKUP_ADDED_LOCK_SETTINGS) {
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of lock settings data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ if (nBytes > 0) {
+ in.readFully(buffer, 0, nBytes);
+ restoreLockSettings(buffer, nBytes);
+ }
+ }
+
if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
} else {
data.close();
@@ -676,6 +708,9 @@
return oldChecksum;
}
try {
+ if (DEBUG_BACKUP) {
+ Log.v(TAG, "Writing entity " + key + " of size " + data.length);
+ }
output.writeEntityHeader(key, data.length);
output.writeEntityData(data, data.length);
} catch (IOException ioe) {
@@ -714,6 +749,31 @@
}
}
+ /**
+ * Serialize the owner info settings
+ */
+ private byte[] getLockSettings() {
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
+ final boolean ownerInfoEnabled = lockPatternUtils.isOwnerInfoEnabled();
+ final String ownerInfo = lockPatternUtils.getOwnerInfo(UserHandle.myUserId());
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(baos);
+ try {
+ out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED);
+ out.writeUTF(ownerInfoEnabled ? "1" : "0");
+ if (ownerInfo != null) {
+ out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO);
+ out.writeUTF(ownerInfo != null ? ownerInfo : "");
+ }
+ // End marker
+ out.writeUTF("");
+ out.flush();
+ } catch (IOException ioe) {
+ }
+ return baos.toByteArray();
+ }
+
private void restoreSettings(BackupDataInput data, Uri contentUri,
HashSet<String> movedToGlobal) {
byte[] settings = new byte[data.getDataSize()];
@@ -797,6 +857,50 @@
}
/**
+ * Restores the owner info enabled and owner info settings in LockSettings.
+ *
+ * @param buffer
+ * @param nBytes
+ */
+ private void restoreLockSettings(byte[] buffer, int nBytes) {
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, nBytes);
+ DataInputStream in = new DataInputStream(bais);
+ try {
+ String key;
+ // Read until empty string marker
+ while ((key = in.readUTF()).length() > 0) {
+ final String value = in.readUTF();
+ if (DEBUG_BACKUP) {
+ Log.v(TAG, "Restoring lock_settings " + key + " = " + value);
+ }
+ switch (key) {
+ case KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED:
+ lockPatternUtils.setOwnerInfoEnabled("1".equals(value));
+ break;
+ case KEY_LOCK_SETTINGS_OWNER_INFO:
+ lockPatternUtils.setOwnerInfo(value, UserHandle.myUserId());
+ break;
+ }
+ }
+ in.close();
+ } catch (IOException ioe) {
+ }
+ }
+
+ private void restoreLockSettings(BackupDataInput data) {
+ final byte[] settings = new byte[data.getDataSize()];
+ try {
+ data.readEntityData(settings, 0, settings.length);
+ } catch (IOException ioe) {
+ Log.e(TAG, "Couldn't read entity data");
+ return;
+ }
+ restoreLockSettings(settings, settings.length);
+ }
+
+ /**
* Given a cursor and a set of keys, extract the required keys and
* values and write them to a byte array.
*
@@ -941,6 +1045,7 @@
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStreamWriter out = new OutputStreamWriter(bos);
fromFile.write(out);
+ out.flush();
return bos.toByteArray();
} else {
return EMPTY_DATA;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 466ddde..2c63647 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -779,7 +779,7 @@
// Special cases for location providers (sigh).
if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
- return updateLocationProvidersAllowed(value, owningUserId);
+ return updateLocationProvidersAllowedLocked(value, owningUserId);
}
// Mutate the value.
@@ -1072,7 +1072,7 @@
*
* @returns whether the enabled location providers changed.
*/
- private boolean updateLocationProvidersAllowed(String value, int owningUserId) {
+ private boolean updateLocationProvidersAllowedLocked(String value, int owningUserId) {
if (TextUtils.isEmpty(value)) {
return false;
}
@@ -1130,10 +1130,9 @@
return false;
}
- updateSecureSettingLocked(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- newProviders, owningUserId);
-
- return true;
+ return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
+ getCallingPackage());
}
private void sendNotify(Uri uri, int userId) {
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1d8cb46..f7bbce0 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -79,7 +79,8 @@
android:layout_width="@dimen/notification_panel_width"
android:layout_height="match_parent"
android:layout_gravity="@integer/notification_panel_layout_gravity"
- android:layout_marginBottom="@dimen/close_handle_underlap" />
+ android:layout_marginBottom="@dimen/close_handle_underlap"
+ android:importantForAccessibility="no" />
<ViewStub
android:id="@+id/keyguard_user_switcher"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 08e7f4f..45f4290 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Versteek <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Dit sal verskyn die volgende keer wanneer jy dit in instellings aanskakel."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Versteek"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wil die volumedialoog wees."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Laat toe"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Weier"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is die volumedialoog"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Raak om die oorspronklike terug te stel."</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 11a85cc..aac7a2f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ይደበቅ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"በቅንብሮች ውስጥ በሚቀጥለው ጊዜ እንዲበራ በሚያደርጉበት ጊዜ ዳግመኛ ብቅ ይላል።"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ደብቅ"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው መሆን ይፈልጋል።"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ፍቀድ"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ከልክል"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው ነው"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"የመጀመሪያውን ወደነበረበት ለመመለስ ይንኩ።"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index e3b2bee..447196a 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -373,14 +373,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"هل تريد إخفاء <xliff:g id="TILE_LABEL">%1$s</xliff:g>؟"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"سيظهر مرة أخرى عند تمكينه في الإعدادات المرة التالية."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"إخفاء"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"يريد <xliff:g id="APP_NAME">%1$s</xliff:g> أن يكون مربع حوار مستوى الصوت."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"سماح"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رفض"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> هو مربع حوار مستوى الصوت"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"المس لاستعادة الإعداد الأصلي."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6d20387..a058c39 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Да се скрие ли „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Бързите настройки ще се покажат отново следващия път, когато ги включите от „Настройки“."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Скриване"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска да изпълнява ролята на диалоговия прозорец за силата на звука."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Разрешаване"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Отказване"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> изпълнява ролята на диалоговия прозорец за силата на звука"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Докоснете, за да възстановите оригинала."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 79d576d..8805acf 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> লুকাবেন?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"আপনি পরের বার সেটিংস-এ এটি চালু করলে এটি উপস্থিত হবে"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"লুকান"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ভলিউম ডায়লগ হতে চায়৷"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"মঞ্জুরি দিন"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"প্রত্যাখ্যান করুন"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"আসলটি পুনঃস্থাপন করতে স্পর্শ করুন৷"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 50e4112..1b9987c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vols amagar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tornarà a mostrar-se la propera vegada que l\'activis a la configuració."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Amaga"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> vol passar a ser el diàleg del volum."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permet"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denega"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> és el diàleg de volum"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca per restaurar l\'original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ec954a1..c5ee2fb 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -373,14 +373,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skrýt <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tato položka se znovu zobrazí, až ji v nastavení znovu zapnete."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skrýt"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> chce být dialogem hlasitosti."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Povolit"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmítnout"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialog hlasitosti"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index b467a3a..11f1640 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igen, næste gang du aktiverer den i indstillingerne."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ønsker at være dialogboksen for lydstyrke."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Tillad"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afvis"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryk for at gendanne originalen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 0c0cee7..4bf3076 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ausblenden?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Sie wird wieder eingeblendet, wenn Sie sie in den Einstellungen erneut aktivieren."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ausblenden"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> will die Lautstärke regeln."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Zulassen"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ablehnen"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Zum Wiederherstellen des Originals hier tippen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 2517d2b..d5a7b2b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Απόκρυψη <xliff:g id="TILE_LABEL">%1$s</xliff:g>;"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Θα εμφανιστεί ξανά την επόμενη φορά που θα το ενεργοποιήσετε στις ρυθμίσεις."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Απόκρυψη"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> θέλει να γίνει το παράθυρο διαλόγου ελέγχου έντασης"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Να επιτραπεί"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Απόρριψη"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Αγγίξτε για επαναφορά αρχικού."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 8faef53..a7c929b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"It will reappear the next time you turn it on in settings."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Hide"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wants to be the volume dialogue."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Allow"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 8faef53..a7c929b 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"It will reappear the next time you turn it on in settings."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Hide"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wants to be the volume dialogue."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Allow"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 248de9c..aeef5b7 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Volverá a aparecer la próxima vez que se active en la configuración."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> quiere ser el cuadro de diálogo de volumen."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar el original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b850733..39e83a4 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Volverá a aparecer la próxima vez que actives esta opción en Ajustes."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> quiere ser el cuadro de diálogo de volumen."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar la versión original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index b4bcea1..d58bc52 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Kas peita <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"See kuvatakse uuesti järgmisel korral, kui selle seadetes sisse lülitate."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Peida"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> tahab olla helitugevuse dialoog."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Luba"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Keela"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Originaali taastamiseks puudutage."</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 454a8ca..1753575 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ezkutatu nahi duzu?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ezarpenetan aktibatzen duzun hurrengoan agertuko da berriro."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ezkutatu"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> bolumenaren leihoa izan nahian ari da."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Baimendu"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ukatu"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> da bolumenaren leihoa"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Ukitu jatorrizkora leheneratzeko"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index dae1d36..a704494 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> مخفی شود؟"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"دفعه بعد که آن را روشن کنید، در تنظیمات نشان داده میشود."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"پنهان کردن"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> میخواهد کنترلکننده صدا باشد."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"مجاز"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رد کردن"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترلکننده صدا است"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"برای بازیابی کنترلکننده اصلی، لمس کنید."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 7a32323..4480bda7 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Piilotetaanko <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Se tulee takaisin näkyviin, kun seuraavan kerran otat sen käyttöön asetuksissa."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Piilota"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> haluaa olla äänenvoimakkuusvalinta."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Salli"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Estä"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on äänenvoimakkuusvalinta."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Palauta alkuperäinen koskettamalla."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index e7fa6a9f..49dd20a 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Cet élément réapparaîtra la prochaine fois que vous l\'activerez dans les paramètres."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Masquer"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> souhaite être la boîte de dialogue du volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Autoriser"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Touchez pour restaurer l\'original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5bd5157..4b3f42a 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g> ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Cet élément réapparaîtra la prochaine fois que vous l\'activerez dans les paramètres."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Masquer"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> souhaite être la boîte de dialogue du volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Autoriser"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Appuyez pour restaurer l\'interface d\'origine."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 22369e0..350a50f 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Queres ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Volverá aparecer a próxima vez que se active na configuración."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> quere ser o cadro de diálogo de volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rexeitar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é o cadro de diálogo de volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar o orixinal."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 8999999..73ec483 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> को छिपाएं?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"जब आप उसे अगली बार सेटिंग में चालू करेंगे तो वह फिर से दिखाई देगी."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"छिपाएं"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद होना चाहता है."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"अनुमति दें"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार करें"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल को पुनर्स्थापित करने के लिए स्पर्श करें."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 2197459..be21b3c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -370,14 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite li sakriti pločicu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ponovo će se pojaviti kada je sljedeći put uključite u postavkama."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Sakrij"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> želi biti dijaloški okvir za upravljanje glasnoćom."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Dopusti"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odbij"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> predstavlja dijaloški okvir za upravljanje glasnoćom"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da biste vratili izvorno."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 341b3e1..5d6a599 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Elrejti ezt: <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Újból megjelenik majd, amikor ismét engedélyezi a beállítások között."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Elrejtés"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás szeretné kezelni a hangerőt."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Engedélyezés"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Elutasítás"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás kezeli a hangerőt"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Érintse meg az eredeti érték visszaállításához."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index a681f10..abef9a0 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Թաքցնե՞լ <xliff:g id="TILE_LABEL">%1$s</xliff:g>-ը:"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Այն դարձյալ կհայտնվի, երբ նորից միացնեք կարգավորումներում:"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Թաքցնել"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ցանկանում է երկխոսության հավելվածը դառնալ:"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Թույլատրել"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Մերժել"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Դիպչեք՝ սկզբնօրինակը վերականգնելու համար:"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 819dd8f..451983d 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ini akan muncul kembali saat Anda mengaktifkannya dalam setelan."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Sembunyikan"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ingin menjadi dialog volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Izinkan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> adalah dialog volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan aslinya."</string>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index d688fca..c616ab3 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fela <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Þetta birtist aftur næst þegar þú kveikir á því í stillingunum."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Fela"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> vill vera hljóðstyrksvalmyndin."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Leyfa"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Hafna"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er hljóðstyrksvalmyndin"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Snertu til að færa í upprunalegt horf."</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 9f03609..a9a7297 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Nascondere <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Verranno visualizzate di nuovo quando le riattiverai nelle impostazioni."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Nascondi"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> desidera fungere da finestra di dialogo relativa al volume"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Consenti"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Nega"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> rappresenta la finestra di dialogo relativa al volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tocca per ripristinare l\'originale."</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b602158..70de38d 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"להסתיר<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"יופיע מחדש בפעם הבאה שתפעיל את האפשרות בהגדרות."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"הסתר"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> מנסה לפעול בתור תיבת הדו-שיח של עוצמת הקול."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"התר"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"דחה"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"גע כדי לשחזר את עוצמת הקול המקורית."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 722c836..1b44396 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>を非表示にしますか?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"次回、設定でONにすると再表示されます。"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"非表示"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>が音量ダイアログとして機能します。"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"許可"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"許可しない"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"タップすると元の音量ダイアログが復元されます。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 1a2c624..1bf9099 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -80,7 +80,7 @@
<string name="accessibility_back" msgid="567011538994429120">"უკან"</string>
<string name="accessibility_home" msgid="8217216074895377641">"საწყისი"</string>
<string name="accessibility_menu" msgid="316839303324695949">"მენიუ"</string>
- <string name="accessibility_recent" msgid="5208608566793607626">"გადახედვა"</string>
+ <string name="accessibility_recent" msgid="5208608566793607626">"მიმოხილვა"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"ძიება"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"კამერა"</string>
<string name="accessibility_phone_button" msgid="6738112589538563574">"ტელეფონი"</string>
@@ -166,7 +166,7 @@
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"სწრაფი პარამეტრები"</string>
<string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"ეკრანის დაბლოკვა."</string>
<string name="accessibility_desc_settings" msgid="3417884241751434521">"პარამეტრები"</string>
- <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"გადახედვა."</string>
+ <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"მიმოხილვა"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"მომხმარებელი: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi გამორთულია."</string>
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"დაიმალოს <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"ის კვლავ გამოჩნდება, როდესაც პარამეტრებში ჩართავთ"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"დამალვა"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> სურს იყოს ხმოვან დიალოგში."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"უფლების მიცემა"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"უარყოფა"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ხმოვან დიალოგშია"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ორიგინალის აღდგენისათვის, შეეხეთ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 3efd5cd..805fca6 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жасыру керек пе?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ол сіз оны параметрлерде келесі қосқанда қайта пайда болады."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Жасыру"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> көлем диалогтық терезесі болғысы келеді."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Рұқсат беру"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Өшіру"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнұсқаны қалпына келтіру үшін түртіңіз."</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index d24ccda..52dd68c 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"លាក់ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"វានឹងបង្ហាញពេលក្រោយ ពេលដែលអ្នកបើកក្នុងការកំណត់។"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"លាក់"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ចង់ក្លាយជាប្រអប់សម្លេង។"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"អនុញ្ញាត"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"បដិសេធ"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ប៉ះដើម្បីស្តារច្បាប់ដើម។"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 9446616..6df8655 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ಮರೆಮಾಡುವುದೇ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"ನೀವು ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಅದನ್ನು ಆನ್ ಮಾಡಿದಾಗ ಅದು ಮರುಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ಮರೆಮಾಡಿ"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಲು ಬಯಸುತ್ತದೆ."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ಅನುಮತಿಸು"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ನಿರಾಕರಿಸು"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ಮೂಲ ಮರುಸ್ಥಾಪಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index f33873a..d2a35cd 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -394,14 +394,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жашырылсынбы?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Бул кийинки жолу жөндөөлөрдөн күйгүзүлгөндө кайра көрүнөт."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Жашыруу"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу болгусу келет."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Уруксат берүү"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Жок"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнусканы калыбына келтирүү үчүн тийип коюңуз."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 27b22e96..1b523a2 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Slėpti „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tai bus vėl parodyta, kai kitą kartą įjungsite tai nustatymuose."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Slėpti"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ nori būti garsumo valdymo dialogo langu."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Leisti"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Atmesti"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Palieskite, kad atkurtumėte originalą."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 157575f..4461006 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -370,14 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vai paslēpt vienumu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tas tiks atkārtoti parādīts, kad nākamreiz ieslēgsiet to iestatījumos."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Paslēpt"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> vēlas pārvaldīt skaļuma dialoglodziņu."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Atļaut"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neatļaut"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Pieskarieties, lai atjaunotu sākotnējo."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index b6be2c9..d65bf65 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сокриј <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ќе се појави повторно следниот пат кога ќе го вклучите во поставки."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Сокриј"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> сака да биде дијалог за јачина на звук."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Овозможи"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> е дијалог за јачина на звук"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Допрете за да го вратите оригиналот."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 56dd34f..467453e 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> എന്നത് മറയ്ക്കണോ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"അടുത്ത തവണ നിങ്ങൾ അത് ക്രമീകരണങ്ങളിൽ ഓണാക്കുമ്പോൾ അത് വീണ്ടും ദൃശ്യമാകും."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"മറയ്ക്കുക"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗ് ആകാൻ താൽപ്പര്യപ്പെടുന്നു."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"അനുവദിക്കുക"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"നിരസിക്കുക"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"യഥാർത്ഥമായത് പുനഃസ്ഥാപിക്കാൻ സ്പർശിക്കുക."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 10b855d..9399957 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> लपवायचे?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"आपण सेटिंग्जमध्ये ते पुढील वेळी चालू कराल तेव्हा ते पुन्हा दिसेल."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"लपवा"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा आकारमान संवाद होऊ इच्छितो."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"अनुमती द्या"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"नकार द्या"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा आकारमान संवाद आहे"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"मूळ पुनर्संचयित करण्यासाठी स्पर्श करा."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 218485e..72783a5 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Mesej itu akan terpapar semula pada kali seterusnya anda menghidupkan apl dalam tetapan."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Sembunyikan"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> mahu menjadi dialog kelantangan."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Benarkan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan yang asal."</string>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 966ca9e..6043929 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ဝှက်မည်လား?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"နောက်တစ်ကြိမ်သင် ချိန်ညှိချက်များဖွင့်လျှင် ၎င်းပေါ်လာပါမည်။"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ဖျောက်ထားမည်"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည်အသံဒိုင်ယာလော့ခ်ဖြစ်လိုပါသည်။"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ခွင့်ပြုသည်"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ငြင်းပယ်သည်"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အသံဒိုင်ယာလော့ခ်ဖြစ်သည်"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"မူရင်းအားပြန်လည်သိမ်းဆည်းရန် ထိပါ။"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index f06cc66..9ea954e 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igjen neste gang du slår den på i innstillingene."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ønsker å være volumdialogen."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Tillat"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ikke tillat"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er volumdialogen"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Trykk for å gå tilbake til den opprinnelige volumdialogen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index b8afe9b..38b4d56 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"लुकाउनुहुन्छ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"यो तपाईं सेटिङ् मा यो बारी अर्को समय देखापर्नेछ।"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"लुकाउनुहोस्"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद बन्न चाहन्छ।"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"अनुमति दिनुहोस्"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार गर्नुहोस्"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद हो"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल पुन: भण्डार गर्न छुनुहोस्।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 9aca0f8..be46153 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> verbergen?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Deze wordt opnieuw weergegeven zodra u de instelling weer inschakelt."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Verbergen"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wil het volumedialoogvenster zijn."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Toestaan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afwijzen"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is het volumedialoogvenster"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tik hierop om het origineel te herstellen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c0d939f..5e6c632 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ukryć <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Pojawi się ponownie, gdy następnym włączysz go w ustawieniach."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ukryj"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> chce sterować głośnością."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Zezwól"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmów"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> steruje głośnością"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotknij, by przywrócić pierwotną."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d5bb452..b9977ff 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Pretende ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Reaparecerá da próxima vez que a funcionalidade for ativada nas definições."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> pretende ser a caixa de diálogo do volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Recusar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo do volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c92e03f1..90913c9 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ela reaparecerá na próxima vez que você ativá-la nas configurações."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> deseja ser a caixa de diálogo referente ao volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Negar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index f638c17..2b815ab 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -370,14 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ascundeți <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Va reapărea la următoarea activare în setări."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ascundeți"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> dorește să afișeze caseta de dialog pentru volum."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permiteți"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuzați"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Atingeți pentru a reveni la setarea inițială."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index fb007af..8904be2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -373,14 +373,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Скрыть параметр \"<xliff:g id="TILE_LABEL">%1$s</xliff:g>\"?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Этот параметр появится в следующий раз, когда вы включите его."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Скрыть"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"Назначить приложение <xliff:g id="APP_NAME">%1$s</xliff:g> регулятором громкости?"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Да"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Нет"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> назначено регулятором громкости"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Нажмите, чтобы восстановить приложение по умолчанию."</string>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index bb28fc9..f8d2293 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> සඟවන්නද?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"ඊළඟ අවස්ථාවේ සැකසීම් තුළ ඔබ එය සක්රිය කළ විට එය නැවත දිසිවේ."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"සඟවන්න"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> හට ධාරිතා සංවාදය වීමට අවශ්යයි"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ඉඩ දෙන්න"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ප්රතික්ෂේප කරන්න"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"මුල් තත්වය නැවත ප්රතිසාධනය කිරීමට ස්පර්ශ කරන්න."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f3ab6de..ddb45b4a 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -373,14 +373,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skryť <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Táto položka sa znova zobrazí, keď ju v nastaveniach opätovne zapnete."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skryť"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> chce byť dialógom hlasitosti"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Povoliť"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmietnuť"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialóg hlasitosti"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 826dfd2..24b92c4 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite skriti <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Znova se bo pojavila, ko jo naslednjič vklopite v nastavitvah."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skrij"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> želi biti pogovorno okno glede prostornine."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Dovoli"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Zavrni"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotaknite se, če želite obnoviti izvirnik."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 13b5fb6..552b377 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -370,14 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Желите ли да сакријете <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ово ће се поново појавити када га следећи пут будете укључили у подешавањима."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Сакриј"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> жели да буде дијалог за јачину звука."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Дозволи"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> је дијалог за јачину звука"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Додирните да бисте вратили оригинал."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0abb8c9..c8587c0 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vill du dölja <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den visas på nytt nästa gång du aktiverar den i inställningarna."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Dölj"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> försöker överta funktionen som volymkontroll."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Tillåt"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neka"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> används som volymkontroll"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryck här om du vill återställa den ursprungliga appen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 70a5809..d933224 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ungependa kuficha <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Itaonekana tena wakati mwingine utakapoiwasha katika mipangilio."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ficha"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> inataka kuwa mazungumzo ya sauti."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Ruhusu"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Kataa"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ni mazungumzo ya sauti"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Gusa ili urejeshe ya awali."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index e211645..c9a7459 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ஐ மறைக்கவா?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"அடுத்த முறை அமைப்புகளில் மீண்டும் இயக்கும்போது, இது மீண்டும் தோன்றும்."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"மறை"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>, ஒலியளவு செய்தியாகச் செயல்பட விரும்புகிறது."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"அனுமதி"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"நிராகரி"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"அசலை மீட்டமைக்கத் தொடவும்."</string>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 21eb37c..481acc3 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ని దాచాలా?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"మీరు సెట్టింగ్ల్లో దీన్ని ఆన్ చేసిన తదుపరిసారి ఇది కనిపిస్తుంది."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"దాచు"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్గా ఉండాలనుకుంటోంది."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"అనుమతించు"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"తిరస్కరించు"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"అసలుదాన్ని పునరుద్ధరించడానికి తాకండి."</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 6af2b0f..2aab5ff 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ซ่อน <xliff:g id="TILE_LABEL">%1$s</xliff:g> ไหม"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"จะปรากฏอีกครั้งเมื่อคุณเปิดใช้ในการตั้งค่าครั้งถัดไป"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ซ่อน"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ต้องการเป็่นช่องโต้ตอบระดับเสียง"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"อนุญาต"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ปฏิเสธ"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"แตะเพื่อคืนค่าดั้งเดิม"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2a816f0..5a36fb2 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Itago ang <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Lalabas itong muli sa susunod na pagkakataon na i-on mo ito sa mga setting."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Itago"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"Gusto ng <xliff:g id="APP_NAME">%1$s</xliff:g> na maging volume dialog."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Payagan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tanggihan"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Pindutin upang ibalik ang orihinal."</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d90eb79..ccecdba 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сховати <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"З’явиться знову, коли ви ввімкнете його в налаштуваннях."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Сховати"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> може стати діалоговим вікном налаштування гучності."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Дозволити"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Відхилити"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> – діалогове вікно налаштування гучності"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Торкніться, щоб відновити оригінал."</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 445e1f3..2e1f94f 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> berkitilsinmi?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Keyingi safar sozlamalardan yoqilgan paydo bo‘ladi."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Berkitish"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqarmoqchi."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Ruxsat berish"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rad etish"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqaradi"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Aslini tiklash uchun bosing."</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 47b09da8..d3e7a14 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ẩn <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Thông báo này sẽ xuất hiện lại vào lần tiếp theo bạn bật thông báo trong cài đặt."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ẩn"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> muốn trở thành hộp thoại khối lượng."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Cho phép"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Từ chối"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Chạm để khôi phục bản gốc."</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index a86af82..a352a23 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏 <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"下一次您在設定開啟它時,它將再次出現。"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"隱藏"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」想成為音量對話。"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"允許"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸即可復原。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2ee2782..7cef5aa 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -371,14 +371,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"只要在設定頁面中重新啟用,就能再次看到快捷設定選項。"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"隱藏"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> 想成為預設的音量控制對話方塊。"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"允許"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> 現在是預設的音量控制對話方塊。"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸即可還原為原始的音量控制對話方塊。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 5cd9e4b..7bb54d6 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -369,14 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fihla i-<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Izovela ngesikhathi esilandelayo uma uvule lesi silungiselelo."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Fihla"</string>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ifuna ukuba yingxoxo yevolumu."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Vumela"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Phika"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> yingxoxo yevolumu"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Thinta ukuze ubuyisele kokwangempela."</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0420d35..d8b6a82 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -217,8 +217,6 @@
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="camera_label">open camera</string>
- <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_ime_switch_button">Switch input method button.</string>
<!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_compatibility_zoom_button">Compatibility zoom button.</string>
@@ -483,17 +481,17 @@
<string name="accessibility_brightness">Display brightness</string>
<!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_3g_title">2G-3G data is off</string>
+ <string name="data_usage_disabled_dialog_3g_title">2G-3G data is paused</string>
<!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_4g_title">4G data is off</string>
+ <string name="data_usage_disabled_dialog_4g_title">4G data is paused</string>
<!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_mobile_title">Cellular data is off</string>
+ <string name="data_usage_disabled_dialog_mobile_title">Cellular data is paused</string>
<!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_title">Data is off</string>
+ <string name="data_usage_disabled_dialog_title">Data is paused</string>
<!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
- <string name="data_usage_disabled_dialog">Your device turned off data because it reached the limit you set.\n\nTurning it back on may lead to charges from your carrier.</string>
+ <string name="data_usage_disabled_dialog">Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your carrier.</string>
<!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
- <string name="data_usage_disabled_dialog_enable">Turn on data</string>
+ <string name="data_usage_disabled_dialog_enable">Resume</string>
<!-- Text to display underneath the graphical signal strength meter when
no connection is available. [CHAR LIMIT=20] -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b1ac733..e0b4c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -193,8 +193,7 @@
}
// Start loading tasks according to the load plan
- ArrayList<TaskStack> stacks = plan.getAllTaskStacks();
- if (stacks.size() == 0) {
+ if (!plan.hasTasks()) {
loader.preloadTasks(plan, mConfig.launchedFromHome);
}
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -203,11 +202,11 @@
loadOpts.numVisibleTaskThumbnails = mConfig.launchedNumVisibleThumbnails;
loader.loadTasks(this, plan, loadOpts);
- boolean hasTasks = plan.hasTasks();
- if (hasTasks) {
+ ArrayList<TaskStack> stacks = plan.getAllTaskStacks();
+ mConfig.launchedWithNoRecentTasks = !plan.hasTasks();
+ if (!mConfig.launchedWithNoRecentTasks) {
mRecentsView.setTaskStacks(stacks);
}
- mConfig.launchedWithNoRecentTasks = !hasTasks;
// Create the home intent runnable
Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
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 2318319..21975b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -879,7 +879,7 @@
// Start the focus animation when alt-tabbing
if (mConfig.launchedWithAltTab && !mConfig.launchedHasConfigurationChanged) {
- TaskView tv = taskViews.get(mFocusedTaskIndex);
+ TaskView tv = getChildViewForTask(mStack.getTasks().get(mFocusedTaskIndex));
if (tv != null) {
tv.setFocusedTask(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index b827acc..81e960a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -32,12 +32,10 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
@@ -104,11 +102,10 @@
});
// Load the dismiss resources
- Resources res = context.getResources();
- mLightDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_light);
- mDarkDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_dark);
+ mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
+ mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
mDismissContentDescription =
- res.getString(R.string.accessibility_recents_item_will_be_dismissed);
+ context.getString(R.string.accessibility_recents_item_will_be_dismissed);
// Configure the highlight paint
if (sHighlightPaint == null) {
@@ -283,23 +280,26 @@
}
if (focused) {
+ int currentColor = mBackgroundColor;
int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
int[][] states = new int[][] {
+ new int[] {},
new int[] { android.R.attr.state_enabled },
new int[] { android.R.attr.state_pressed }
};
int[] newStates = new int[]{
+ 0,
android.R.attr.state_enabled,
android.R.attr.state_pressed
};
int[] colors = new int[] {
+ currentColor,
secondaryColor,
secondaryColor
};
mBackground.setColor(new ColorStateList(states, colors));
mBackground.setState(newStates);
// Pulse the background color
- int currentColor = mBackgroundColor;
int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
currentColor, lightPrimaryColor);
@@ -326,7 +326,7 @@
mFocusAnimator = new AnimatorSet();
mFocusAnimator.playTogether(backgroundColor, translation);
- mFocusAnimator.setStartDelay(750);
+ mFocusAnimator.setStartDelay(150);
mFocusAnimator.setDuration(750);
mFocusAnimator.start();
} else {
diff --git a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
index c8b080e..b4613d6 100644
--- a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -34,6 +34,7 @@
import android.text.TextUtils;
import android.util.Property;
import android.util.Slog;
+import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MagnificationSpec;
@@ -110,7 +111,6 @@
private static final int STATE_MAGNIFIED_INTERACTION = 4;
private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
- private static final int MULTI_TAP_TIME_SLOP_ADJUSTMENT = 50;
private static final int MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED = 1;
private static final int MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED = 2;
@@ -135,9 +135,8 @@
private final AccessibilityManagerService mAms;
- private final int mTapTimeSlop = ViewConfiguration.getTapTimeout();
- private final int mMultiTapTimeSlop =
- ViewConfiguration.getDoubleTapTimeout() - MULTI_TAP_TIME_SLOP_ADJUSTMENT;
+ private final int mTapTimeSlop = ViewConfiguration.getJumpTapTimeout();
+ private final int mMultiTapTimeSlop;
private final int mTapDistanceSlop;
private final int mMultiTapDistanceSlop;
@@ -192,6 +191,9 @@
mWindowManager = LocalServices.getService(WindowManagerInternal.class);
mAms = service;
+ mMultiTapTimeSlop = ViewConfiguration.getDoubleTapTimeout()
+ + mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screen_magnification_multi_tap_adjustment);
mLongAnimationDuration = context.getResources().getInteger(
com.android.internal.R.integer.config_longAnimTime);
mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop();
@@ -481,15 +483,20 @@
private static final float MIN_SCALE = 1.3f;
private static final float MAX_SCALE = 5.0f;
- private static final float SCALING_THRESHOLD = 0.3f;
-
private final ScaleGestureDetector mScaleGestureDetector;
private final GestureDetector mGestureDetector;
+ private final float mScalingThreshold;
+
private float mInitialScaleFactor = -1;
private boolean mScaling;
public MagnifiedContentInteractonStateHandler(Context context) {
+ final TypedValue scaleValue = new TypedValue();
+ context.getResources().getValue(
+ com.android.internal.R.dimen.config_screen_magnification_scaling_threshold,
+ scaleValue, false);
+ mScalingThreshold = scaleValue.getFloat();
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mScaleGestureDetector.setQuickScaleEnabled(false);
mGestureDetector = new GestureDetector(context, this);
@@ -537,7 +544,7 @@
mInitialScaleFactor = detector.getScaleFactor();
} else {
final float deltaScale = detector.getScaleFactor() - mInitialScaleFactor;
- if (Math.abs(deltaScale) > SCALING_THRESHOLD) {
+ if (Math.abs(deltaScale) > mScalingThreshold) {
mScaling = true;
return true;
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7623514..da11dad 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2837,10 +2837,10 @@
return providersUpdated;
}
- private boolean removeHostsAndProvidersForPackageLocked(String pkgName, int userId) {
+ private boolean removeProvidersForPackageLocked(String pkgName, int userId) {
boolean removed = false;
- int N = mProviders.size();
+ final int N = mProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (pkgName.equals(provider.info.provider.getPackageName())
@@ -2849,11 +2849,16 @@
removed = true;
}
}
+ return removed;
+ }
+
+ private boolean removeHostsAndProvidersForPackageLocked(String pkgName, int userId) {
+ boolean removed = removeProvidersForPackageLocked(pkgName, userId);
// Delete the hosts for this package too
// By now, we have removed any AppWidgets that were in any hosts here,
// so we don't need to worry about sending DISABLE broadcasts to them.
- N = mHosts.size();
+ final int N = mHosts.size();
for (int i = N - 1; i >= 0; i--) {
Host host = mHosts.get(i);
if (pkgName.equals(host.id.packageName)
@@ -2925,13 +2930,30 @@
synchronized (mLock) {
boolean providersChanged = false;
+ ArraySet<String> previousPackages = new ArraySet<String>();
+ final int providerCount = mProviders.size();
+ for (int i = 0; i < providerCount; ++i) {
+ Provider provider = mProviders.get(i);
+ if (provider.getUserId() == userId) {
+ previousPackages.add(provider.id.componentName.getPackageName());
+ }
+ }
+
final int packageCount = packages.size();
for (int i = 0; i < packageCount; i++) {
String packageName = packages.get(i);
+ previousPackages.remove(packageName);
providersChanged |= updateProvidersForPackageLocked(packageName,
userId, null);
}
+ // Some packages are no longer whitelisted.
+ final int removedCount = previousPackages.size();
+ for (int i = 0; i < removedCount; ++i) {
+ providersChanged |= removeProvidersForPackageLocked(
+ previousPackages.valueAt(i), userId);
+ }
+
if (providersChanged) {
saveGroupStateAsync(userId);
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
@@ -3142,10 +3164,10 @@
if (parentId != callerId) {
return false;
}
- return isProviderWhitelListed(packageName, profileId);
+ return isProviderWhiteListed(packageName, profileId);
}
- public boolean isProviderWhitelListed(String packageName, int profileId) {
+ public boolean isProviderWhiteListed(String packageName, int profileId) {
DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
DevicePolicyManagerInternal.class);
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 912a181..b3b4651 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -626,6 +626,22 @@
pw.println(" voltage: " + mBatteryProps.batteryVoltage);
pw.println(" temperature: " + mBatteryProps.batteryTemperature);
pw.println(" technology: " + mBatteryProps.batteryTechnology);
+
+ } else if ("unplug".equals(args[0])) {
+ if (!mUpdatesStopped) {
+ mLastBatteryProps.set(mBatteryProps);
+ }
+ mBatteryProps.chargerAcOnline = false;
+ mBatteryProps.chargerUsbOnline = false;
+ mBatteryProps.chargerWirelessOnline = false;
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mUpdatesStopped = true;
+ processValuesLocked(false);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
} else if (args.length == 3 && "set".equals(args[0])) {
String key = args[1];
String value = args[2];
@@ -662,6 +678,7 @@
} catch (NumberFormatException ex) {
pw.println("Bad value: " + value);
}
+
} else if (args.length == 1 && "reset".equals(args[0])) {
long ident = Binder.clearCallingIdentity();
try {
@@ -676,6 +693,7 @@
} else {
pw.println("Dump current battery state, or:");
pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ pw.println(" unplug");
pw.println(" reset");
}
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 77b8b31..895a5c3 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.admin.DevicePolicyManager;
+import android.app.backup.BackupManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -46,6 +47,7 @@
import android.text.TextUtils;
import android.util.Slog;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
@@ -257,6 +259,9 @@
private void setStringUnchecked(String key, int userId, String value) {
mStorage.writeKeyValue(key, value, userId);
+ if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
+ BackupManager.dataChanged("com.android.providers.settings");
+ }
}
@Override
@@ -463,6 +468,11 @@
Secure.LOCK_SCREEN_OWNER_INFO
};
+ private static final String[] SETTINGS_TO_BACKUP = new String[] {
+ Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
+ Secure.LOCK_SCREEN_OWNER_INFO
+ };
+
private IMountService getMountService() {
final IBinder service = ServiceManager.getService("mount");
if (service != null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 50820ff..6229778 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2256,31 +2256,33 @@
if (MONITOR_CPU_USAGE &&
mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
mLastCpuTime.set(now);
- haveNewCpuStats = true;
mProcessCpuTracker.update();
- //Slog.i(TAG, mProcessCpu.printCurrentState());
- //Slog.i(TAG, "Total CPU usage: "
- // + mProcessCpu.getTotalCpuPercent() + "%");
+ if (mProcessCpuTracker.hasGoodLastStats()) {
+ haveNewCpuStats = true;
+ //Slog.i(TAG, mProcessCpu.printCurrentState());
+ //Slog.i(TAG, "Total CPU usage: "
+ // + mProcessCpu.getTotalCpuPercent() + "%");
- // Slog the cpu usage if the property is set.
- if ("true".equals(SystemProperties.get("events.cpu"))) {
- int user = mProcessCpuTracker.getLastUserTime();
- int system = mProcessCpuTracker.getLastSystemTime();
- int iowait = mProcessCpuTracker.getLastIoWaitTime();
- int irq = mProcessCpuTracker.getLastIrqTime();
- int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
- int idle = mProcessCpuTracker.getLastIdleTime();
+ // Slog the cpu usage if the property is set.
+ if ("true".equals(SystemProperties.get("events.cpu"))) {
+ int user = mProcessCpuTracker.getLastUserTime();
+ int system = mProcessCpuTracker.getLastSystemTime();
+ int iowait = mProcessCpuTracker.getLastIoWaitTime();
+ int irq = mProcessCpuTracker.getLastIrqTime();
+ int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
+ int idle = mProcessCpuTracker.getLastIdleTime();
- int total = user + system + iowait + irq + softIrq + idle;
- if (total == 0) total = 1;
+ int total = user + system + iowait + irq + softIrq + idle;
+ if (total == 0) total = 1;
- EventLog.writeEvent(EventLogTags.CPU,
- ((user+system+iowait+irq+softIrq) * 100) / total,
- (user * 100) / total,
- (system * 100) / total,
- (iowait * 100) / total,
- (irq * 100) / total,
- (softIrq * 100) / total);
+ EventLog.writeEvent(EventLogTags.CPU,
+ ((user+system+iowait+irq+softIrq) * 100) / total,
+ (user * 100) / total,
+ (system * 100) / total,
+ (iowait * 100) / total,
+ (irq * 100) / total,
+ (softIrq * 100) / total);
+ }
}
}
@@ -2289,8 +2291,10 @@
synchronized(bstats) {
synchronized(mPidsSelfLocked) {
if (haveNewCpuStats) {
- if (mOnBattery) {
- int perc = bstats.startAddingCpuLocked();
+ final int perc = bstats.startAddingCpuLocked();
+ if (perc >= 0) {
+ int remainUTime = 0;
+ int remainSTime = 0;
int totalUTime = 0;
int totalSTime = 0;
final int N = mProcessCpuTracker.countStats();
@@ -2302,17 +2306,18 @@
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
int otherUTime = (st.rel_utime*perc)/100;
int otherSTime = (st.rel_stime*perc)/100;
- totalUTime += otherUTime;
- totalSTime += otherSTime;
+ remainUTime += otherUTime;
+ remainSTime += otherSTime;
+ totalUTime += st.rel_utime;
+ totalSTime += st.rel_stime;
if (pr != null) {
BatteryStatsImpl.Uid.Proc ps = pr.curProcBatteryStats;
if (ps == null || !ps.isActive()) {
pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
pr.info.uid, pr.processName);
}
- ps.addCpuTimeLocked(st.rel_utime-otherUTime,
- st.rel_stime-otherSTime);
- ps.addSpeedStepTimes(cpuSpeedTimes);
+ ps.addCpuTimeLocked(st.rel_utime - otherUTime,
+ st.rel_stime - otherSTime, cpuSpeedTimes);
pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
} else {
BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
@@ -2320,13 +2325,19 @@
st.batteryStats = ps = bstats.getProcessStatsLocked(
bstats.mapUid(st.uid), st.name);
}
- ps.addCpuTimeLocked(st.rel_utime-otherUTime,
- st.rel_stime-otherSTime);
- ps.addSpeedStepTimes(cpuSpeedTimes);
+ ps.addCpuTimeLocked(st.rel_utime - otherUTime,
+ st.rel_stime - otherSTime, cpuSpeedTimes);
}
}
- bstats.finishAddingCpuLocked(perc, totalUTime,
- totalSTime, cpuSpeedTimes);
+ final int userTime = mProcessCpuTracker.getLastUserTime();
+ final int systemTime = mProcessCpuTracker.getLastSystemTime();
+ final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime();
+ final int irqTime = mProcessCpuTracker.getLastIrqTime();
+ final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
+ final int idleTime = mProcessCpuTracker.getLastIdleTime();
+ bstats.finishAddingCpuLocked(perc, remainUTime,
+ remainSTime, totalUTime, totalSTime, userTime, systemTime,
+ iowaitTime, irqTime, softIrqTime, idleTime, cpuSpeedTimes);
}
}
}
@@ -7771,7 +7782,7 @@
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
"getTaskThumbnail()");
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id);
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id, false);
if (tr != null) {
return tr.getTaskThumbnailLocked();
}
@@ -7884,7 +7895,7 @@
@Override
public void setTaskResizeable(int taskId, boolean resizeable) {
synchronized (this) {
- TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, false);
if (task == null) {
Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
return;
@@ -8032,7 +8043,7 @@
* @return Returns true if the given task was found and removed.
*/
private boolean removeTaskByIdLocked(int taskId, boolean killProcess) {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId);
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId, false);
if (tr != null) {
tr.removeTaskActivitiesLocked();
cleanUpRemovedTaskLocked(tr, killProcess);
@@ -8285,7 +8296,7 @@
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId);
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId, false);
return tr != null && tr.stack != null && tr.stack.isHomeStack();
}
} finally {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4d7305d..7afe23a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4171,6 +4171,8 @@
}
mActivityContainer.onTaskListEmptyLocked();
}
+
+ task.stack = null;
}
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1aa2a10..9fe3c48 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -462,6 +462,16 @@
}
TaskRecord anyTaskForIdLocked(int id) {
+ return anyTaskForIdLocked(id, true);
+ }
+
+ /**
+ * Returns a {@link TaskRecord} for the input id if available. Null otherwise.
+ * @param id Id of the task we would like returned.
+ * @param restoreFromRecents If the id was not in the active list, but was found in recents,
+ * restore the task from recents to the active list.
+ */
+ TaskRecord anyTaskForIdLocked(int id, boolean restoreFromRecents) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
@@ -482,6 +492,10 @@
return null;
}
+ if (!restoreFromRecents) {
+ return task;
+ }
+
if (!restoreRecentTaskLocked(task)) {
if (DEBUG_RECENTS) Slog.w(TAG, "Couldn't restore task id=" + id + " found in recents");
return null;
@@ -516,7 +530,7 @@
if (mCurTaskId <= 0) {
mCurTaskId = 1;
}
- } while (anyTaskForIdLocked(mCurTaskId) != null);
+ } while (anyTaskForIdLocked(mCurTaskId, false) != null);
return mCurTaskId;
}
@@ -2661,7 +2675,7 @@
final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack tmpStack = homeDisplayStacks.get(stackNdx);
- if (!tmpStack.isHomeStack()) {
+ if (!tmpStack.isHomeStack() && tmpStack.mFullscreen) {
stack = tmpStack;
break;
}
@@ -3928,6 +3942,10 @@
}
void onTaskListEmptyLocked() {
+ mHandler.removeMessages(CONTAINER_TASK_LIST_EMPTY_TIMEOUT, this);
+ detachLocked();
+ deleteActivityContainer(this);
+ mHandler.obtainMessage(CONTAINER_CALLBACK_TASK_LIST_EMPTY, this).sendToTarget();
}
@Override
@@ -4016,13 +4034,6 @@
return false;
}
- void onTaskListEmptyLocked() {
- mHandler.removeMessages(CONTAINER_TASK_LIST_EMPTY_TIMEOUT, this);
- detachLocked();
- deleteActivityContainer(this);
- mHandler.obtainMessage(CONTAINER_CALLBACK_TASK_LIST_EMPTY, this).sendToTarget();
- }
-
private void setSurfaceIfReadyLocked() {
if (DEBUG_STACK) Slog.v(TAG, "setSurfaceIfReadyLocked: mDrawn=" + mDrawn +
" mContainerState=" + mContainerState + " mSurface=" + mSurface);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4ea62ec..02c8cce 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -581,8 +581,7 @@
AudioSystem.setErrorCallback(mAudioSystemCallback);
- boolean cameraSoundForced = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_camera_sound_forced);
+ boolean cameraSoundForced = readCameraSoundForced();
mCameraSoundForced = new Boolean(cameraSoundForced);
sendMsg(mAudioHandler,
MSG_SET_FORCE_USE,
@@ -1107,11 +1106,6 @@
for (int stream = 0; stream < mStreamStates.length; stream++) {
if (streamTypeAlias == mStreamVolumeAlias[stream]) {
mStreamStates[stream].mute(state);
-
- Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, stream);
- intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
- sendBroadcastToAll(intent);
}
}
} else if ((direction == AudioManager.ADJUST_RAISE) &&
@@ -1459,16 +1453,6 @@
flags = updateFlagsForSystemAudio(flags);
}
mVolumeController.postVolumeChanged(streamType, flags);
-
- if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) {
- oldIndex = (oldIndex + 5) / 10;
- index = (index + 5) / 10;
- Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
- intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
- intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
- sendBroadcastToAll(intent);
- }
}
// If Hdmi-CEC system audio mode is on, we show volume bar only when TV
@@ -3506,6 +3490,7 @@
private int mIndexMax;
private final ConcurrentHashMap<Integer, Integer> mIndex =
new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
+ private final Intent mVolumeChanged;
private VolumeStreamState(String settingName, int streamType) {
@@ -3517,6 +3502,8 @@
mIndexMax *= 10;
readSettings();
+ mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
+ mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
}
public String getSettingNameForDevice(int device) {
@@ -3631,8 +3618,10 @@
}
public boolean setIndex(int index, int device) {
+ boolean changed = false;
+ int oldIndex;
synchronized (VolumeStreamState.class) {
- int oldIndex = getIndex(device);
+ oldIndex = getIndex(device);
index = getValidIndex(index);
synchronized (mCameraSoundForced) {
if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
@@ -3641,7 +3630,8 @@
}
mIndex.put(device, index);
- if (oldIndex != index) {
+ changed = oldIndex != index;
+ if (changed) {
// Apply change to all streams using this one as alias
// if changing volume of current device, also change volume of current
// device on aliased stream
@@ -3659,11 +3649,16 @@
}
}
}
- return true;
- } else {
- return false;
}
}
+ if (changed) {
+ oldIndex = (oldIndex + 5) / 10;
+ index = (index + 5) / 10;
+ mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
+ mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
+ sendBroadcastToAll(mVolumeChanged);
+ }
+ return changed;
}
public int getIndex(int device) {
@@ -3720,9 +3715,12 @@
}
public void mute(boolean state) {
+ boolean changed = false;
synchronized (VolumeStreamState.class) {
if (state != mIsMuted) {
+ changed = true;
mIsMuted = state;
+
// Set the new mute volume. This propagates the values to
// the audio system, otherwise the volume won't be changed
// at the lower level.
@@ -3734,6 +3732,13 @@
this, 0);
}
}
+ if (changed) {
+ // Stream mute changed, fire the intent.
+ Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
+ sendBroadcastToAll(intent);
+ }
}
public int getStreamType() {
@@ -5071,6 +5076,12 @@
return mMediaFocusControl.getCurrentAudioFocus();
}
+ private boolean readCameraSoundForced() {
+ return SystemProperties.getBoolean("audio.camerasound.force", false) ||
+ mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_camera_sound_forced);
+ }
+
//==========================================================================================
// Device orientation
//==========================================================================================
@@ -5101,8 +5112,7 @@
null,
0);
- boolean cameraSoundForced = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_camera_sound_forced);
+ boolean cameraSoundForced = readCameraSoundForced();
synchronized (mSettingsLock) {
boolean cameraSoundForcedChanged = false;
synchronized (mCameraSoundForced) {
@@ -5517,6 +5527,7 @@
pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
pw.print(" mMcc="); pw.println(mMcc);
+ pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
pw.print(" mHasVibrator="); pw.println(mHasVibrator);
pw.print(" mControllerService="); pw.println(mControllerService);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 1a0f81d..06c154e 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.media.AudioManager;
+import android.media.AudioManagerInternal;
import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.IRemoteVolumeController;
@@ -59,6 +60,7 @@
import android.util.SparseArray;
import android.view.KeyEvent;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
import com.android.server.Watchdog.Monitor;
@@ -94,6 +96,7 @@
private KeyguardManager mKeyguardManager;
private IAudioService mAudioService;
private AudioManager mAudioManager;
+ private AudioManagerInternal mAudioManagerInternal;
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
@@ -121,6 +124,7 @@
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService();
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+ mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mContentResolver = getContext().getContentResolver();
mSettingsObserver = new SettingsObserver();
mSettingsObserver.observe();
@@ -343,7 +347,13 @@
}
}
- private void enforceStatusBarPermission(String action, int pid, int uid) {
+ private void enforceSystemUiPermission(String action, int pid, int uid) {
+ if (mAudioManagerInternal != null) {
+ final int vcuid = mAudioManagerInternal.getVolumeControllerUid();
+ if (vcuid > 0 && uid == vcuid) {
+ return;
+ }
+ }
if (getContext().checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
pid, uid) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Only system ui may " + action);
@@ -789,7 +799,7 @@
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- enforceStatusBarPermission("listen for volume changes", pid, uid);
+ enforceSystemUiPermission("listen for volume changes", pid, uid);
mRvc = rvc;
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 69a1ac9..2729392 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -28,7 +28,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -36,6 +35,7 @@
import android.os.Handler;
import android.os.IUserManager;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -111,6 +111,7 @@
private static final String USER_INFO_DIR = "system" + File.separator + "users";
private static final String USER_LIST_FILENAME = "userlist.xml";
private static final String USER_PHOTO_FILENAME = "photo.png";
+ private static final String USER_PHOTO_FILENAME_TMP = USER_PHOTO_FILENAME + ".tmp";
private static final String RESTRICTIONS_FILE_PREFIX = "res_";
private static final String XML_SUFFIX = ".xml";
@@ -433,7 +434,8 @@
}
@Override
- public Bitmap getUserIcon(int userId) {
+ public ParcelFileDescriptor getUserIcon(int userId) {
+ String iconPath;
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
if (info == null || info.partial) {
@@ -448,8 +450,16 @@
if (info.iconPath == null) {
return null;
}
- return BitmapFactory.decodeFile(info.iconPath);
+ iconPath = info.iconPath;
}
+
+ try {
+ return ParcelFileDescriptor.open(
+ new File(iconPath), ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "Couldn't find icon file", e);
+ }
+ return null;
}
public void makeInitialized(int userId) {
@@ -572,6 +582,7 @@
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
File file = new File(dir, USER_PHOTO_FILENAME);
+ File tmp = new File(dir, USER_PHOTO_FILENAME_TMP);
if (!dir.exists()) {
dir.mkdir();
FileUtils.setPermissions(
@@ -580,7 +591,8 @@
-1, -1);
}
FileOutputStream os;
- if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(file))) {
+ if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp))
+ && tmp.renameTo(file)) {
info.iconPath = file.getAbsolutePath();
}
try {
@@ -588,6 +600,7 @@
} catch (IOException ioe) {
// What the ... !
}
+ tmp.delete();
} catch (FileNotFoundException e) {
Slog.w(LOG_TAG, "Error setting photo for user ", e);
}
@@ -1787,7 +1800,8 @@
public int getUserHandle(int userSerialNumber) {
synchronized (mPackagesLock) {
for (int userId : mUserIds) {
- if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId;
+ UserInfo info = getUserInfoLocked(userId);
+ if (info != null && info.serialNumber == userSerialNumber) return userId;
}
// Not found
return -1;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 271ec75..b90d263 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -457,6 +457,7 @@
static final Rect mTmpNavigationFrame = new Rect();
WindowState mTopFullscreenOpaqueWindowState;
+ WindowState mTopFullscreenOpaqueOrDimmingWindowState;
HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
boolean mTopIsFullscreen;
@@ -3972,6 +3973,7 @@
@Override
public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
mTopFullscreenOpaqueWindowState = null;
+ mTopFullscreenOpaqueOrDimmingWindowState = null;
mAppsToBeHidden.clear();
mAppsThatDismissKeyguard.clear();
mForceStatusBar = false;
@@ -4060,6 +4062,9 @@
&& attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
+ if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
+ mTopFullscreenOpaqueOrDimmingWindowState = win;
+ }
if (!mAppsThatDismissKeyguard.isEmpty() &&
mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
if (DEBUG_LAYOUT) Slog.v(TAG,
@@ -4085,6 +4090,11 @@
}
}
}
+ if (mTopFullscreenOpaqueOrDimmingWindowState == null
+ && win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()
+ && win.isDimming()) {
+ mTopFullscreenOpaqueOrDimmingWindowState = win;
+ }
}
/** {@inheritDoc} */
@@ -6051,6 +6061,7 @@
if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
+ tmpVisibility = updateLightStatusBarLw(tmpVisibility);
final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int diff = visibility ^ mLastSystemUiFlags;
final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
@@ -6079,6 +6090,26 @@
return diff;
}
+ private int updateLightStatusBarLw(int vis) {
+ WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
+ ? mStatusBar
+ : mTopFullscreenOpaqueOrDimmingWindowState;
+
+ if (statusColorWin != null) {
+ if (statusColorWin == mTopFullscreenOpaqueWindowState) {
+ // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+ // its light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
+ & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ } else if (statusColorWin != null && statusColorWin.isDimming()) {
+ // Otherwise if it's dimming, clear the light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ }
+ }
+ return vis;
+ }
+
private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
// apply translucent bar vis flags
WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
@@ -6383,6 +6414,10 @@
pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
pw.println(mTopFullscreenOpaqueWindowState);
}
+ if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
+ pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
+ pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
+ }
if (mForcingShowNavBar) {
pw.print(prefix); pw.print("mForcingShowNavBar=");
pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 50b2262..c5f4161 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -699,15 +699,14 @@
private void findAudioSinkFromAudioPolicy(List<AudioDevicePort> sinks) {
sinks.clear();
- ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>();
+ ArrayList<AudioDevicePort> devicePorts = new ArrayList<AudioDevicePort>();
if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) {
return;
}
int sinkDevice = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC);
- for (AudioPort port : devicePorts) {
- AudioDevicePort devicePort = (AudioDevicePort) port;
- if ((devicePort.type() & sinkDevice) != 0) {
- sinks.add(devicePort);
+ for (AudioDevicePort port : devicePorts) {
+ if ((port.type() & sinkDevice) != 0) {
+ sinks.add(port);
}
}
}
@@ -716,14 +715,13 @@
if (type == AudioManager.DEVICE_NONE) {
return null;
}
- ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>();
+ ArrayList<AudioDevicePort> devicePorts = new ArrayList<AudioDevicePort>();
if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) {
return null;
}
- for (AudioPort port : devicePorts) {
- AudioDevicePort devicePort = (AudioDevicePort) port;
- if (devicePort.type() == type && devicePort.address().equals(address)) {
- return devicePort;
+ for (AudioDevicePort port : devicePorts) {
+ if (port.type() == type && port.address().equals(address)) {
+ return port;
}
}
return null;
diff --git a/services/core/java/com/android/server/wm/FocusedStackFrame.java b/services/core/java/com/android/server/wm/FocusedStackFrame.java
index f1f5fe8..826fe97 100644
--- a/services/core/java/com/android/server/wm/FocusedStackFrame.java
+++ b/services/core/java/com/android/server/wm/FocusedStackFrame.java
@@ -16,14 +16,14 @@
package com.android.server.wm;
-import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
+import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.Region;
import android.util.Slog;
import android.view.Display;
import android.view.Surface.OutOfResourcesException;
@@ -35,14 +35,17 @@
class FocusedStackFrame {
private static final String TAG = "FocusedStackFrame";
- private static final int THICKNESS = 10;
+ private static final boolean DEBUG = false;
+ private static final int THICKNESS = 2;
private static final float ALPHA = 0.3f;
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
+ private final Paint mInnerPaint = new Paint();
+ private final Paint mOuterPaint = new Paint();
+ private final Rect mBounds = new Rect();
private final Rect mLastBounds = new Rect();
- final Rect mBounds = new Rect();
- private final Rect mTmpDrawRect = new Rect();
+ private int mLayer = -1;
public FocusedStackFrame(Display display, SurfaceSession session) {
SurfaceControl ctrl = null;
@@ -60,83 +63,84 @@
} catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
+
+ mInnerPaint.setStyle(Paint.Style.STROKE);
+ mInnerPaint.setStrokeWidth(THICKNESS);
+ mInnerPaint.setColor(Color.WHITE);
+ mOuterPaint.setStyle(Paint.Style.STROKE);
+ mOuterPaint.setStrokeWidth(THICKNESS);
+ mOuterPaint.setColor(Color.BLACK);
}
- private void draw(Rect bounds, int color) {
- if (false && DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() +
- " color=" + Integer.toHexString(color));
- mTmpDrawRect.set(bounds);
+ private void draw() {
+ if (mLastBounds.isEmpty()) {
+ // Currently unset. Set it.
+ mLastBounds.set(mBounds);
+ }
+
+ if (DEBUG) Slog.i(TAG, "draw: mBounds=" + mBounds + " mLastBounds=" + mLastBounds);
+
Canvas c = null;
try {
- c = mSurface.lockCanvas(mTmpDrawRect);
+ c = mSurface.lockCanvas(mLastBounds);
} catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Unable to lock canvas", e);
} catch (Surface.OutOfResourcesException e) {
+ Slog.e(TAG, "Unable to lock canvas", e);
}
if (c == null) {
+ if (DEBUG) Slog.w(TAG, "Canvas is null...");
return;
}
- final int w = bounds.width();
- final int h = bounds.height();
-
- // Top
- mTmpDrawRect.set(0, 0, w, THICKNESS);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
- // Left (not including Top or Bottom stripe).
- mTmpDrawRect.set(0, THICKNESS, THICKNESS, h - THICKNESS);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
- // Right (not including Top or Bottom stripe).
- mTmpDrawRect.set(w - THICKNESS, THICKNESS, w, h - THICKNESS);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
- // Bottom
- mTmpDrawRect.set(0, h - THICKNESS, w, h);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
-
+ c.drawRect(0, 0, mBounds.width(), mBounds.height(), mOuterPaint);
+ c.drawRect(THICKNESS, THICKNESS, mBounds.width() - THICKNESS, mBounds.height() - THICKNESS,
+ mInnerPaint);
+ if (DEBUG) Slog.w(TAG, "c.width=" + c.getWidth() + " c.height=" + c.getHeight()
+ + " c.clip=" + c .getClipBounds());
mSurface.unlockCanvasAndPost(c);
+ mLastBounds.set(mBounds);
}
- private void positionSurface(Rect bounds) {
- if (false && DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString());
- mSurfaceControl.setSize(bounds.width(), bounds.height());
- mSurfaceControl.setPosition(bounds.left, bounds.top);
+ private void setupSurface(boolean visible) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setupSurface");
+ SurfaceControl.openTransaction();
+ try {
+ if (visible) {
+ mSurfaceControl.setPosition(mBounds.left, mBounds.top);
+ mSurfaceControl.setSize(mBounds.width(), mBounds.height());
+ mSurfaceControl.show();
+ } else {
+ mSurfaceControl.hide();
+ }
+ } finally {
+ SurfaceControl.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setupSurface");
+ }
+ }
+
+ void setVisibility(TaskStack stack) {
+ if (stack == null || stack.isFullscreen()) {
+ setupSurface(false);
+ } else {
+ stack.getBounds(mBounds);
+ setupSurface(true);
+ if (!mBounds.equals(mLastBounds)) {
+ draw();
+ }
+ }
}
// Note: caller responsible for being inside
// Surface.openTransaction() / closeTransaction()
- public void setVisibility(boolean on) {
- if (false && DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on +
- " mLastBounds=" + mLastBounds.toShortString() +
- " mBounds=" + mBounds.toShortString());
- if (mSurfaceControl == null) {
+ void setLayer(int layer) {
+ if (mLayer == layer) {
return;
}
- if (on) {
- if (!mLastBounds.equals(mBounds)) {
- // Erase the previous rectangle.
- positionSurface(mLastBounds);
- draw(mLastBounds, Color.TRANSPARENT);
- // Draw the latest rectangle.
- positionSurface(mBounds);
- draw(mBounds, Color.WHITE);
- // Update the history.
- mLastBounds.set(mBounds);
- }
- mSurfaceControl.show();
- } else {
- mSurfaceControl.hide();
- }
- }
-
- public void setBounds(TaskStack stack) {
- stack.getBounds(mBounds);
- if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds);
- }
-
- public void setLayer(int layer) {
- mSurfaceControl.setLayer(layer);
+ mLayer = layer;
+ mSurfaceControl.setLayer(mLayer);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 94fecc9..3e1c5ff 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -26,7 +26,6 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.TypedValue;
-import android.view.Display;
import android.view.Surface;
import com.android.server.EventLogTags;
@@ -371,7 +370,7 @@
for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
- mService.removeWindowInnerLocked(null, appWindows.get(winNdx));
+ mService.removeWindowInnerLocked(appWindows.get(winNdx));
doAnotherLayoutPass = true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9450d16..e238d30 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -64,11 +64,9 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
@@ -127,7 +125,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
@@ -136,7 +133,6 @@
import android.view.WindowManagerPolicy.PointerEventListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.view.animation.Transformation;
import java.io.BufferedWriter;
import java.io.DataInputStream;
@@ -181,7 +177,6 @@
static final boolean DEBUG_CONFIGURATION = false;
static final boolean DEBUG_APP_TRANSITIONS = false;
static final boolean DEBUG_STARTING_WINDOW = false;
- static final boolean DEBUG_REORDER = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
static final boolean DEBUG_DRAG = false;
@@ -413,7 +408,7 @@
* This is set when we have run out of memory, and will either be an empty
* list or contain windows that need to be force removed.
*/
- ArrayList<WindowState> mForceRemoves;
+ final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
/**
* Windows that clients are waiting to have drawn.
@@ -1736,10 +1731,7 @@
}
}
- static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
- static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
-
- int adjustWallpaperWindowsLocked() {
+ boolean adjustWallpaperWindowsLocked() {
mInnerFields.mWallpaperMayChange = false;
boolean targetChanged = false;
@@ -1966,13 +1958,12 @@
// Start stepping backwards from here, ensuring that our wallpaper windows
// are correctly placed.
- int changed = 0;
+ boolean changed = false;
for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
WindowToken token = mWallpaperTokens.get(curTokenNdx);
if (token.hidden == visible) {
if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
"Wallpaper token " + token + " hidden=" + !visible);
- changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
token.hidden = !visible;
// Need to do a layout to ensure the wallpaper now has the correct size.
getDefaultDisplayContentLocked().layoutNeeded = true;
@@ -2033,7 +2024,7 @@
windows.add(insertionIndex, wallpaper);
mWindowsChanged = true;
- changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
+ changed = true;
}
}
@@ -2654,7 +2645,7 @@
}
}
- removeWindowInnerLocked(session, win);
+ removeWindowInnerLocked(win);
// Removing a visible window will effect the computed orientation
// So just update orientation if needed.
if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
@@ -2664,7 +2655,7 @@
Binder.restoreCallingIdentity(origId);
}
- void removeWindowInnerLocked(Session session, WindowState win) {
+ void removeWindowInnerLocked(WindowState win) {
if (win.mRemoved) {
// Nothing to do.
return;
@@ -2674,7 +2665,7 @@
WindowState cwin = win.mChildWindows.get(i);
Slog.w(TAG, "Force-removing child win " + cwin + " from container "
+ win);
- removeWindowInnerLocked(cwin.mSession, cwin);
+ removeWindowInnerLocked(cwin);
}
win.mRemoved = true;
@@ -3663,14 +3654,12 @@
// TODO(multidisplay): Change to the correct display.
final WindowList windows = getDefaultWindowListLocked();
- int pos = windows.size() - 1;
- while (pos >= 0) {
+ for (int pos = windows.size() - 1; pos >= 0; --pos) {
WindowState win = windows.get(pos);
- pos--;
if (win.mAppToken != null) {
// We hit an application window. so the orientation will be determined by the
// app window. No point in continuing further.
- return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ return (mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
continue;
@@ -3682,9 +3671,9 @@
}
if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
- return (mLastWindowForcedOrientation=req);
+ return (mLastWindowForcedOrientation = req);
}
- return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ return (mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
public int getOrientationFromAppTokensLocked() {
@@ -3742,14 +3731,12 @@
// to use the orientation behind it, then just take whatever
// orientation it has and ignores whatever is under it.
lastFullscreen = atoken.appFullscreen;
- if (lastFullscreen
- && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+ if (lastFullscreen && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
+ " -- full screen, return " + or);
return or;
}
- // If this application has requested an explicit orientation,
- // then use it.
+ // If this application has requested an explicit orientation, then use it.
if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
&& or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
@@ -3785,6 +3772,9 @@
private Configuration updateOrientationFromAppTokensLocked(
Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
+ if (!mDisplayReady) {
+ return null;
+ }
Configuration config = null;
if (updateOrientationFromAppTokensLocked(false)) {
@@ -3803,20 +3793,19 @@
// the value of the previous configuration.
mTempConfiguration.setToDefaults();
mTempConfiguration.fontScale = currentConfig.fontScale;
- if (computeScreenConfigurationLocked(mTempConfiguration)) {
- if (currentConfig.diff(mTempConfiguration) != 0) {
- mWaitingForConfig = true;
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- displayContent.layoutNeeded = true;
- int anim[] = new int[2];
- if (displayContent.isDimming()) {
- anim[0] = anim[1] = 0;
- } else {
- mPolicy.selectRotationAnimationLw(anim);
- }
- startFreezingDisplayLocked(false, anim[0], anim[1]);
- config = new Configuration(mTempConfiguration);
+ computeScreenConfigurationLocked(mTempConfiguration);
+ if (currentConfig.diff(mTempConfiguration) != 0) {
+ mWaitingForConfig = true;
+ final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ displayContent.layoutNeeded = true;
+ int anim[] = new int[2];
+ if (displayContent.isDimming()) {
+ anim[0] = anim[1] = 0;
+ } else {
+ mPolicy.selectRotationAnimationLw(anim);
}
+ startFreezingDisplayLocked(false, anim[0], anim[1]);
+ config = new Configuration(mTempConfiguration);
}
}
@@ -3940,20 +3929,7 @@
} else {
stack = null;
}
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
- SurfaceControl.openTransaction();
- try {
- if (stack == null) {
- mFocusedStackFrame.setVisibility(false);
- } else {
- mFocusedStackFrame.setBounds(stack);
- final boolean multipleStacks = !stack.isFullscreen();
- mFocusedStackFrame.setVisibility(multipleStacks);
- }
- } finally {
- SurfaceControl.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
- }
+ mFocusedStackFrame.setVisibility(stack);
}
@Override
@@ -6367,13 +6343,12 @@
screenRotationAnimation =
mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
- // We need to update our screen size information to match the new
- // rotation. Note that this is redundant with the later call to
- // sendNewConfiguration() that must be called after this function
- // returns... however we need to do the screen size part of that
- // before then so we have the correct size to use when initializing
- // the rotation animation for the new rotation.
- computeScreenConfigurationLocked(null);
+ // We need to update our screen size information to match the new rotation. If the rotation
+ // has actually changed then this method will return true and, according to the comment at
+ // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
+ // By updating the Display info here it will be available to
+ // computeScreenConfigurationLocked later.
+ updateDisplayAndOrientationLocked();
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (!inTransaction) {
@@ -6922,9 +6897,11 @@
public Configuration computeNewConfiguration() {
synchronized (mWindowMap) {
+ if (!mDisplayReady) {
+ return null;
+ }
Configuration config = computeNewConfigurationLocked();
- if (config == null && mWaitingForConfig) {
- // Nothing changed but we are waiting for something... stop that!
+ if (mWaitingForConfig) {
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
performLayoutAndPlaceSurfacesLocked();
@@ -6936,9 +6913,7 @@
Configuration computeNewConfigurationLocked() {
Configuration config = new Configuration();
config.fontScale = 0;
- if (!computeScreenConfigurationLocked(config)) {
- return null;
- }
+ computeScreenConfigurationLocked(config);
return config;
}
@@ -7045,11 +7020,8 @@
return sw;
}
- private boolean computeScreenConfigurationLocked(Configuration config) {
- if (!mDisplayReady) {
- return false;
- }
-
+ /** Do not call if mDisplayReady == false */
+ DisplayInfo updateDisplayAndOrientationLocked() {
// TODO(multidisplay): For now, apply Configuration to main screen only.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
@@ -7079,11 +7051,6 @@
}
}
- if (config != null) {
- config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
- Configuration.ORIENTATION_LANDSCAPE;
- }
-
// Update application display metrics.
final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
@@ -7106,89 +7073,98 @@
Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
}
- final DisplayMetrics dm = mDisplayMetrics;
- mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
+ mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
mCompatDisplayMetrics);
+ return displayInfo;
+ }
- if (config != null) {
- config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
- / dm.density);
- config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
- / dm.density);
- computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
+ /** Do not call if mDisplayReady == false */
+ void computeScreenConfigurationLocked(Configuration config) {
+ final DisplayInfo displayInfo = updateDisplayAndOrientationLocked();
- config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
- config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
- config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
- config.densityDpi = displayContent.mBaseDisplayDensity;
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+ config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
+ Configuration.ORIENTATION_LANDSCAPE;
+ config.screenWidthDp =
+ (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) / mDisplayMetrics.density);
+ config.screenHeightDp =
+ (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) / mDisplayMetrics.density);
+ final boolean rotated = (mRotation == Surface.ROTATION_90
+ || mRotation == Surface.ROTATION_270);
+ computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, mDisplayMetrics.density,
+ config);
- // Update the configuration based on available input devices, lid switch,
- // and platform configuration.
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
- config.keyboard = Configuration.KEYBOARD_NOKEYS;
- config.navigation = Configuration.NAVIGATION_NONAV;
+ config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
+ config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
+ config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated,
+ mDisplayMetrics, dw, dh);
+ config.densityDpi = displayInfo.logicalDensityDpi;
- int keyboardPresence = 0;
- int navigationPresence = 0;
- final InputDevice[] devices = mInputManager.getInputDevices();
- final int len = devices.length;
- for (int i = 0; i < len; i++) {
- InputDevice device = devices[i];
- if (!device.isVirtual()) {
- final int sources = device.getSources();
- final int presenceFlag = device.isExternal() ?
- WindowManagerPolicy.PRESENCE_EXTERNAL :
- WindowManagerPolicy.PRESENCE_INTERNAL;
+ // Update the configuration based on available input devices, lid switch,
+ // and platform configuration.
+ config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ config.keyboard = Configuration.KEYBOARD_NOKEYS;
+ config.navigation = Configuration.NAVIGATION_NONAV;
- if (mIsTouchDevice) {
- if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
- InputDevice.SOURCE_TOUCHSCREEN) {
- config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
- }
- } else {
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ int keyboardPresence = 0;
+ int navigationPresence = 0;
+ final InputDevice[] devices = mInputManager.getInputDevices();
+ final int len = devices.length;
+ for (int i = 0; i < len; i++) {
+ InputDevice device = devices[i];
+ if (!device.isVirtual()) {
+ final int sources = device.getSources();
+ final int presenceFlag = device.isExternal() ?
+ WindowManagerPolicy.PRESENCE_EXTERNAL :
+ WindowManagerPolicy.PRESENCE_INTERNAL;
+
+ if (mIsTouchDevice) {
+ if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
+ InputDevice.SOURCE_TOUCHSCREEN) {
+ config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
}
+ } else {
+ config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ }
- if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
- config.navigation = Configuration.NAVIGATION_TRACKBALL;
- navigationPresence |= presenceFlag;
- } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
- && config.navigation == Configuration.NAVIGATION_NONAV) {
- config.navigation = Configuration.NAVIGATION_DPAD;
- navigationPresence |= presenceFlag;
- }
+ if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
+ config.navigation = Configuration.NAVIGATION_TRACKBALL;
+ navigationPresence |= presenceFlag;
+ } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
+ && config.navigation == Configuration.NAVIGATION_NONAV) {
+ config.navigation = Configuration.NAVIGATION_DPAD;
+ navigationPresence |= presenceFlag;
+ }
- if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
- config.keyboard = Configuration.KEYBOARD_QWERTY;
- keyboardPresence |= presenceFlag;
- }
+ if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
+ config.keyboard = Configuration.KEYBOARD_QWERTY;
+ keyboardPresence |= presenceFlag;
}
}
-
- if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
- config.navigation = Configuration.NAVIGATION_DPAD;
- navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
- }
-
- // Determine whether a hard keyboard is available and enabled.
- boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
- if (hardKeyboardAvailable != mHardKeyboardAvailable) {
- mHardKeyboardAvailable = hardKeyboardAvailable;
- mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- }
- if (mShowImeWithHardKeyboard) {
- config.keyboard = Configuration.KEYBOARD_NOKEYS;
- }
-
- // Let the policy update hidden states.
- config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
- config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
- config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
- mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
- return true;
+ if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
+ config.navigation = Configuration.NAVIGATION_DPAD;
+ navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
+ }
+
+ // Determine whether a hard keyboard is available and enabled.
+ boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
+ if (hardKeyboardAvailable != mHardKeyboardAvailable) {
+ mHardKeyboardAvailable = hardKeyboardAvailable;
+ mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ }
+ if (mShowImeWithHardKeyboard) {
+ config.keyboard = Configuration.KEYBOARD_NOKEYS;
+ }
+
+ // Let the policy update hidden states.
+ config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
+ config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
+ config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
+ mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
public boolean isHardKeyboardAvailable() {
@@ -8317,17 +8293,17 @@
// displayContent must not be null
private void reconfigureDisplayLocked(DisplayContent displayContent) {
// TODO: Multidisplay: for now only use with default display.
+ if (!mDisplayReady) {
+ return;
+ }
configureDisplayPolicyLocked(displayContent);
displayContent.layoutNeeded = true;
boolean configChanged = updateOrientationFromAppTokensLocked(false);
mTempConfiguration.setToDefaults();
mTempConfiguration.fontScale = mCurConfiguration.fontScale;
- if (computeScreenConfigurationLocked(mTempConfiguration)) {
- if (mCurConfiguration.diff(mTempConfiguration) != 0) {
- configChanged = true;
- }
- }
+ computeScreenConfigurationLocked(mTempConfiguration);
+ configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;
if (configChanged) {
mWaitingForConfig = true;
@@ -8628,29 +8604,24 @@
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
mInLayout = true;
- boolean recoveringMemory = false;
- try {
- if (mForceRemoves != null) {
- recoveringMemory = true;
- // Wait a little bit for things to settle down, and off we go.
- for (int i=0; i<mForceRemoves.size(); i++) {
- WindowState ws = mForceRemoves.get(i);
- Slog.i(TAG, "Force removing: " + ws);
- removeWindowInnerLocked(ws.mSession, ws);
- }
- mForceRemoves = null;
- Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
- Object tmp = new Object();
- synchronized (tmp) {
- try {
- tmp.wait(250);
- } catch (InterruptedException e) {
- }
+ boolean recoveringMemory = false;
+ if (!mForceRemoves.isEmpty()) {
+ recoveringMemory = true;
+ // Wait a little bit for things to settle down, and off we go.
+ while (!mForceRemoves.isEmpty()) {
+ WindowState ws = mForceRemoves.remove(0);
+ Slog.i(TAG, "Force removing: " + ws);
+ removeWindowInnerLocked(ws);
+ }
+ Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
+ Object tmp = new Object();
+ synchronized (tmp) {
+ try {
+ tmp.wait(250);
+ } catch (InterruptedException e) {
}
}
- } catch (RuntimeException e) {
- Slog.wtf(TAG, "Unhandled exception while force removing for memory", e);
}
try {
@@ -9326,14 +9297,12 @@
/**
* Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- *
- * @param w WindowState this method is applied to.
- * @param currentTime The time which animations use for calculating transitions.
+ * @param w WindowState this method is applied to.
* @param innerDw Width of app window.
* @param innerDh Height of app window.
*/
- private void handleNotObscuredLocked(final WindowState w, final long currentTime,
- final int innerDw, final int innerDh) {
+ private void handleNotObscuredLocked(final WindowState w,
+ final int innerDw, final int innerDh) {
final WindowManager.LayoutParams attrs = w.mAttrs;
final int attrFlags = attrs.flags;
final boolean canBeSeen = w.isDisplayedLw();
@@ -9452,8 +9421,6 @@
+ Debug.getCallers(3));
}
- final long currentTime = SystemClock.uptimeMillis();
-
int i;
boolean updateInputWindowsNeeded = false;
@@ -9544,8 +9511,7 @@
if ((displayContent.pendingLayoutChanges &
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
- (adjustWallpaperWindowsLocked() &
- ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
+ adjustWallpaperWindowsLocked()) {
assignLayersLocked(windows);
displayContent.layoutNeeded = true;
}
@@ -9610,7 +9576,7 @@
// Update effect.
w.mObscured = mInnerFields.mObscured;
if (!mInnerFields.mObscured) {
- handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
+ handleNotObscuredLocked(w, innerDw, innerDh);
}
if (stack != null && !stack.testDimmingTag()) {
@@ -9989,7 +9955,7 @@
DisplayContentList displayList = new DisplayContentList();
for (i = 0; i < N; i++) {
WindowState w = mPendingRemoveTmp[i];
- removeWindowInnerLocked(w.mSession, w);
+ removeWindowInnerLocked(w);
final DisplayContent displayContent = w.getDisplayContent();
if (displayContent != null && !displayList.contains(displayContent)) {
displayList.add(displayContent);
@@ -10165,10 +10131,6 @@
EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
winAnimator.mSession.mPid, operation);
- if (mForceRemoves == null) {
- mForceRemoves = new ArrayList<WindowState>();
- }
-
long callingIdentity = Binder.clearCallingIdentity();
try {
// There was some problem... first, do a sanity check of the
@@ -10350,6 +10312,10 @@
+ ", flags=" + win.mAttrs.flags
+ ", canReceive=" + win.canReceiveKeys());
+ if (!win.canReceiveKeys()) {
+ continue;
+ }
+
AppWindowToken wtoken = win.mAppToken;
// If this window's application has been removed, just skip it.
@@ -10359,10 +10325,6 @@
continue;
}
- if (!win.canReceiveKeys()) {
- continue;
- }
-
// Descend through all of the app tokens and find the first that either matches
// win.mAppToken (return win) or mFocusedApp (return null).
if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 99cc03e..d58b2b0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1288,6 +1288,15 @@
return displayContent.isDefaultDisplay;
}
+ @Override
+ public boolean isDimming() {
+ TaskStack stack = getStack();
+ if (stack == null) {
+ return false;
+ }
+ return stack.isDimming(mWinAnimator);
+ }
+
public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
mShowToOwnerOnly = showToOwnerOnly;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index f0e02bc..57ed876 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -39,7 +39,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.PrintWriter;
import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
/**
@@ -320,5 +322,23 @@
this.admin = admin;
this.packageName = admin.getPackageName();
}
+ public void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "admin=" + admin);
+ pw.println(prefix + "name=" + name);
+ pw.println();
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ if (mDeviceOwner != null) {
+ pw.println(prefix + "Device Owner: ");
+ mDeviceOwner.dump(prefix + " ", pw);
+ }
+ if (mProfileOwners != null) {
+ for (Map.Entry<Integer, OwnerInfo> entry : mProfileOwners.entrySet()) {
+ pw.println(prefix + "Profile Owner (User " + entry.getKey() + "): ");
+ entry.getValue().dump(prefix + " ", pw);
+ }
+ }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7ff7827..770da5b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -100,6 +100,7 @@
import com.android.internal.os.storage.ExternalStorageFormatter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
@@ -1920,13 +1921,11 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
validateQualityConstant(quality);
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.passwordQuality != quality) {
@@ -1969,11 +1968,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLength != length) {
@@ -2016,11 +2013,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.passwordHistoryLength != length) {
@@ -2063,14 +2058,10 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ Preconditions.checkArgumentNonnegative(timeout, "Timeout must be >= 0 ms");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
- if (timeout < 0) {
- throw new IllegalArgumentException("Timeout must be >= 0 ms");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
// Calling this API automatically bumps the expiration date
@@ -2232,11 +2223,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordUpperCase != length) {
@@ -2276,11 +2265,9 @@
}
public void setPasswordMinimumLowerCase(ComponentName who, int length) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLowerCase != length) {
@@ -2323,11 +2310,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLetters != length) {
@@ -2370,11 +2355,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordNumeric != length) {
@@ -2417,11 +2400,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordSymbols != length) {
@@ -2464,11 +2445,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordNonLetter != length) {
@@ -2561,11 +2540,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(who,
@@ -2772,11 +2749,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
if (ap.maximumTimeToUnlock != timeMs) {
@@ -2955,9 +2930,7 @@
@Override
public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
@@ -3297,9 +3270,7 @@
return null;
}
synchronized(this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
// Only check if owner has set global proxy. We don't allow other users to set it.
DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
@@ -3435,12 +3406,10 @@
if (!mHasFeature) {
return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
// Check for permissions
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
// Only owner can set storage encryption
if (userHandle != UserHandle.USER_OWNER
|| UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
@@ -3571,11 +3540,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (ap.disableScreenCapture != disabled) {
@@ -3630,11 +3597,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (admin.requireAutoTime != required) {
@@ -3682,11 +3647,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
if (ap.disableCamera != disabled) {
@@ -3731,12 +3694,10 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
enforceNotManagedProfile(userHandle, "disable keyguard features");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
if (ap.disabledKeyguardFeatures != which) {
@@ -3880,9 +3841,7 @@
@Override
public void clearDeviceOwner(String packageName) {
- if (packageName == null) {
- throw new NullPointerException("packageName is null");
- }
+ Preconditions.checkNotNull(packageName, "packageName is null");
try {
int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
if (uid != Binder.getCallingUid()) {
@@ -4007,12 +3966,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- // Check for permissions
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
// Check if this is the profile owner who is calling
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
@@ -4034,12 +3990,8 @@
@Override
public void setProfileName(ComponentName who, String profileName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int userId = UserHandle.getCallingUserId();
-
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
// Check if this is the profile owner (includes device owner).
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -4187,7 +4139,9 @@
synchronized (this) {
p.println("Current Device Policy Manager state:");
-
+ if (mDeviceOwner != null) {
+ mDeviceOwner.dump(" ", pw);
+ }
int userCount = mUserData.size();
for (int u = 0; u < userCount; u++) {
DevicePolicyData policy = getUserData(mUserData.keyAt(u));
@@ -4215,12 +4169,9 @@
@Override
public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
ComponentName activity) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
@@ -4237,12 +4188,9 @@
@Override
public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
@@ -4259,12 +4207,9 @@
@Override
public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4281,15 +4226,11 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(admin, "admin is null");
+ Preconditions.checkNotNull(agent, "agent is null");
final int userHandle = UserHandle.getCallingUserId();
enforceNotManagedProfile(userHandle, "set trust agent configuration");
synchronized (this) {
- if (admin == null) {
- throw new NullPointerException("admin is null");
- }
- if (agent == null) {
- throw new NullPointerException("agent is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
@@ -4303,10 +4244,8 @@
if (!mHasFeature) {
return null;
}
+ Preconditions.checkNotNull(agent, "agent null");
enforceCrossUserPermission(userHandle);
- if (agent == null) {
- throw new NullPointerException("agent is null");
- }
synchronized (this) {
final String componentName = agent.flattenToString();
@@ -4359,10 +4298,8 @@
@Override
public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userHandle = UserHandle.getCallingUserId();
@@ -4384,11 +4321,9 @@
}
public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
@@ -4411,11 +4346,9 @@
}
public void clearCrossProfileIntentFilters(ComponentName who) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
long id = Binder.clearCallingIdentity();
@@ -4485,9 +4418,7 @@
if (!mHasFeature) {
return false;
}
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
if (packageList != null) {
int userId = UserHandle.getCallingUserId();
@@ -4532,10 +4463,7 @@
if (!mHasFeature) {
return null;
}
-
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -4640,9 +4568,7 @@
if (!mHasFeature) {
return false;
}
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
// TODO When InputMethodManager supports per user calls remove
// this restriction.
@@ -4685,10 +4611,7 @@
if (!mHasFeature) {
return null;
}
-
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -4761,10 +4684,8 @@
@Override
public UserHandle createUser(ComponentName who, String name) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4815,10 +4736,8 @@
@Override
public boolean removeUser(ComponentName who, UserHandle userHandle) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4832,10 +4751,8 @@
@Override
public boolean switchUser(ComponentName who, UserHandle userHandle) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4856,12 +4773,10 @@
@Override
public Bundle getApplicationRestrictions(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4875,12 +4790,10 @@
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabled) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
final int userHandle = user.getIdentifier();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
@@ -4982,11 +4895,9 @@
@Override
public boolean setApplicationHidden(ComponentName who, String packageName,
boolean hidden) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -5005,11 +4916,9 @@
@Override
public boolean isApplicationHidden(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -5028,11 +4937,8 @@
@Override
public void enableSystemApp(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5073,11 +4979,8 @@
@Override
public int enableSystemAppWithIntent(ComponentName who, Intent intent) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5144,10 +5047,8 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (disabled) {
@@ -5185,12 +5086,9 @@
@Override
public void setUninstallBlocked(ComponentName who, String packageName,
boolean uninstallBlocked) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = UserHandle.getCallingUserId();
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -5237,10 +5135,8 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (admin.disableCallerId != disabled) {
@@ -5255,12 +5151,8 @@
if (!mHasFeature) {
return false;
}
-
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.disableCallerId;
@@ -5281,13 +5173,11 @@
* Sets which packages may enter lock task mode.
*
* This function can only be called by the device owner.
- * @param components The list of components allowed to enter lock task mode.
+ * @param packages The list of packages allowed to enter lock task mode.
*/
public void setLockTaskPackages(ComponentName who, String[] packages) throws SecurityException {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
int userHandle = Binder.getCallingUserHandle().getIdentifier();
@@ -5309,15 +5199,13 @@
* This function returns the list of components allowed to start the task lock mode.
*/
public String[] getLockTaskPackages(ComponentName who) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
int userHandle = Binder.getCallingUserHandle().getIdentifier();
DevicePolicyData policy = getUserData(userHandle);
- return policy.mLockTaskPackages.toArray(new String[0]);
+ return policy.mLockTaskPackages.toArray(new String[policy.mLockTaskPackages.size()]);
}
}
@@ -5373,11 +5261,9 @@
@Override
public void setGlobalSetting(ComponentName who, String setting, String value) {
final ContentResolver contentResolver = mContext.getContentResolver();
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)) {
@@ -5396,13 +5282,11 @@
@Override
public void setSecureSetting(ComponentName who, String setting, String value) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
final ContentResolver contentResolver = mContext.getContentResolver();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5427,10 +5311,8 @@
@Override
public void setMasterVolumeMuted(ComponentName who, boolean on) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IAudioService iAudioService = IAudioService.Stub.asInterface(
@@ -5447,12 +5329,8 @@
@Override
public boolean isMasterVolumeMuted(ComponentName who) {
- final ContentResolver contentResolver = mContext.getContentResolver();
-
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
AudioManager audioManager =
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index c6f6b85..009d25d 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -153,7 +153,7 @@
// audioDevice - the AudioDevice that was added or removed
// enabled - if true, we're connecting a device (it's arrived), else disconnecting
private void notifyDeviceState(UsbAudioDevice audioDevice, boolean enabled) {
- if (DEBUG) {
+ if (DEBUG) {
Slog.d(TAG, "notifyDeviceState " + enabled + " " + audioDevice);
}
@@ -422,7 +422,7 @@
}
/* package */ void usbDeviceRemoved(UsbDevice usbDevice) {
- if (DEBUG) {
+ if (DEBUG) {
Slog.d(TAG, "deviceRemoved(): " + usbDevice);
}
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 570f5fd..4600b72 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -80,6 +80,9 @@
* ({@code 0}, {@code 1}, {@code 2}, ...) that are generated locally on each phone and could
* collide with values generated on other phones or after a data wipe of a given phone.
*
+ * Important: A non-unique identifier could cause non-deterministic call-log backup/restore
+ * behavior.
+ *
* @return A service-specific unique identifier for this {@code PhoneAccountHandle}.
*/
public String getId() {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 6c5f1c6..bcc1ccc4 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -83,6 +83,12 @@
"android.telecom.action.SHOW_CALL_SETTINGS";
/**
+ * The {@link android.content.Intent} action used to show the respond via SMS settings page.
+ */
+ public static final String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS =
+ "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
+
+ /**
* The {@link android.content.Intent} action used to show the settings page used to configure
* {@link PhoneAccount} preferences.
* @hide
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 94691c0..dda9626 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -29,6 +29,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.telecom.PhoneAccount;
import android.util.Log;
import com.android.internal.telecom.ITelecomService;
@@ -3765,7 +3766,7 @@
/**
* Returns the IMS Registration Status
- *@hide
+ * @hide
*/
public boolean isImsRegistered() {
try {
@@ -4116,4 +4117,21 @@
ServiceState.rilRadioTechnologyToString(type));
}
}
+
+ /**
+ * Returns the subscription ID for the given phone account.
+ * @hide
+ */
+ public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
+ int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ retval = service.getSubIdForPhoneAccount(phoneAccount);
+ }
+ } catch (RemoteException e) {
+ }
+
+ return retval;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bf3ee09..62c8746 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.os.Bundle;
+import android.telecom.PhoneAccount;
import android.telephony.CellInfo;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.NeighboringCellInfo;
@@ -879,4 +880,9 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
String getDeviceId();
+
+ /**
+ * Returns the subscription ID associated with the specified PhoneAccount.
+ */
+ int getSubIdForPhoneAccount(in PhoneAccount phoneAccount);
}
diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
index 7177fc8f..1f2b939 100644
--- a/tests/HwAccelerationTest/res/layout/projection_clipping.xml
+++ b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
@@ -14,13 +14,13 @@
android:id="@+id/clickable1"
android:layout_width="100dp"
android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackground"/>
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
<View
android:id="@+id/clickable2"
android:translationX="50dp"
android:translationY="10dp"
android:layout_width="150dp"
android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackground"/>
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
</FrameLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index b8eaa2d..54525ad 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -253,7 +253,7 @@
for f in clazz.fields:
if "static" in f.split and "final" in f.split:
if re.match("[A-Z0-9_]+", f.name) is None:
- error(clazz, f, "C2", "Constant field names should be FOO_NAME")
+ error(clazz, f, "C2", "Constant field names must be FOO_NAME")
def verify_enums(clazz):
@@ -269,7 +269,7 @@
if re.match("android\.R\.[a-z]+", clazz.fullname): return
if re.search("[A-Z]{2,}", clazz.name) is not None:
- warn(clazz, None, "S1", "Class name style should be Mtp not MTP")
+ warn(clazz, None, "S1", "Class names with acronyms should be Mtp not MTP")
if re.match("[^A-Z]", clazz.name):
error(clazz, None, "S1", "Class must start with uppercase char")
@@ -282,7 +282,7 @@
for m in clazz.methods:
if re.search("[A-Z]{2,}", m.name) is not None:
- warn(clazz, m, "S1", "Method name style should be getMtu() instead of getMTU()")
+ warn(clazz, m, "S1", "Method names with acronyms should be getMtu() instead of getMTU()")
if re.match("[^a-z]", m.name):
error(clazz, m, "S1", "Method name must start with lowercase char")
@@ -294,13 +294,13 @@
if clazz.fullname == "android.speech.tts.SynthesisCallback": return
if clazz.name.endswith("Callbacks"):
- error(clazz, None, "L1", "Class name must not be plural")
+ error(clazz, None, "L1", "Callback class names should be singular")
if clazz.name.endswith("Observer"):
warn(clazz, None, "L1", "Class should be named FooCallback")
if clazz.name.endswith("Callback"):
if "interface" in clazz.split:
- error(clazz, None, "CL3", "Callback must be abstract class to enable extension in future API levels")
+ error(clazz, None, "CL3", "Callbacks must be abstract class to enable extension in future API levels")
for m in clazz.methods:
if not re.match("on[A-Z][a-z]*", m.name):
@@ -316,7 +316,7 @@
if clazz.name.endswith("Listener"):
if " abstract class " in clazz.raw:
- error(clazz, None, "L1", "Listener should be an interface, otherwise renamed Callback")
+ error(clazz, None, "L1", "Listeners should be an interface, or otherwise renamed Callback")
for m in clazz.methods:
if not re.match("on[A-Z][a-z]*", m.name):
@@ -325,7 +325,7 @@
if len(clazz.methods) == 1 and clazz.name.startswith("On"):
m = clazz.methods[0]
if (m.name + "Listener").lower() != clazz.name.lower():
- error(clazz, m, "L1", "Single listener method name should match class name")
+ error(clazz, m, "L1", "Single listener method name must match class name")
def verify_actions(clazz):
@@ -412,10 +412,10 @@
"""Verify that no protected methods or fields are allowed."""
for m in clazz.methods:
if "protected" in m.split:
- error(clazz, m, "M7", "No protected methods; must be public")
+ error(clazz, m, "M7", "Protected methods not allowed; must be public")
for f in clazz.fields:
if "protected" in f.split:
- error(clazz, f, "M7", "No protected fields; must be public")
+ error(clazz, f, "M7", "Protected fields not allowed; must be public")
def verify_fields(clazz):
@@ -449,10 +449,10 @@
if not "static" in f.split:
if not re.match("[a-z]([a-zA-Z]+)?", f.name):
- error(clazz, f, "S1", "Non-static fields must be named with myField style")
+ error(clazz, f, "S1", "Non-static fields must be named using myField style")
if re.match("[ms][A-Z]", f.name):
- error(clazz, f, "F1", "Don't expose your internal objects")
+ error(clazz, f, "F1", "Internal objects must not be exposed")
if re.match("[A-Z_]+", f.name):
if "static" not in f.split or "final" not in f.split:
@@ -496,7 +496,7 @@
"""Verify synchronized methods aren't exposed."""
for m in clazz.methods:
if "synchronized" in m.split:
- error(clazz, m, "M5", "Internal lock exposed")
+ error(clazz, m, "M5", "Internal locks must not be exposed")
def verify_intent_builder(clazz):
@@ -508,7 +508,7 @@
if m.name.startswith("create") and m.name.endswith("Intent"):
pass
else:
- error(clazz, m, "FW1", "Methods creating an Intent should be named createFooIntent()")
+ error(clazz, m, "FW1", "Methods creating an Intent must be named createFooIntent()")
def verify_helper_classes(clazz):
@@ -537,7 +537,7 @@
if f.name == "PROVIDER_INTERFACE":
found = True
if f.value != clazz.fullname:
- error(clazz, f, "C4", "Inconsistent interface name; expected %s" % (clazz.fullname))
+ error(clazz, f, "C4", "Inconsistent interface constant; expected %s" % (clazz.fullname))
if "extends android.content.BroadcastReceiver" in clazz.raw:
test_methods = True
@@ -578,11 +578,11 @@
if m.name.startswith("clear"): continue
if m.name.startswith("with"):
- warn(clazz, m, None, "Builder methods names should follow setFoo() style")
+ warn(clazz, m, None, "Builder methods names should use setFoo() style")
if m.name.startswith("set"):
if not m.typ.endswith(clazz.fullname):
- warn(clazz, m, "M4", "Methods should return the builder")
+ warn(clazz, m, "M4", "Methods must return the builder object")
if not has_build:
warn(clazz, None, None, "Missing build() method")
@@ -591,13 +591,13 @@
def verify_aidl(clazz):
"""Catch people exposing raw AIDL."""
if "extends android.os.Binder" in clazz.raw or "implements android.os.IInterface" in clazz.raw:
- error(clazz, None, None, "Exposing raw AIDL interface")
+ error(clazz, None, None, "Raw AIDL interfaces must not be exposed")
def verify_internal(clazz):
"""Catch people exposing internal classes."""
if clazz.pkg.name.startswith("com.android"):
- error(clazz, None, None, "Exposing internal class")
+ error(clazz, None, None, "Internal classes must not be exposed")
def verify_layering(clazz):
@@ -645,25 +645,43 @@
def verify_boolean(clazz, api):
- """Catches people returning boolean from getFoo() style methods.
- Ignores when matching setFoo() is present."""
+ """Verifies that boolean accessors are named correctly.
+ For example, hasFoo() and setHasFoo()."""
- methods = [ m.name for m in clazz.methods ]
+ def is_get(m): return len(m.args) == 0 and m.typ == "boolean"
+ def is_set(m): return len(m.args) == 1 and m.args[0] == "boolean"
- builder = clazz.fullname + ".Builder"
- builder_methods = []
- if builder in api:
- builder_methods = [ m.name for m in api[builder].methods ]
+ gets = [ m for m in clazz.methods if is_get(m) ]
+ sets = [ m for m in clazz.methods if is_set(m) ]
+
+ def error_if_exists(methods, trigger, expected, actual):
+ for m in methods:
+ if m.name == actual:
+ error(clazz, m, "M6", "Symmetric method for %s must be named %s" % (trigger, expected))
for m in clazz.methods:
- if m.typ == "boolean" and m.name.startswith("get") and m.name != "get" and len(m.args) == 0:
- setter = "set" + m.name[3:]
- if setter in methods:
- pass
- elif builder is not None and setter in builder_methods:
- pass
- else:
- warn(clazz, m, None, "Methods returning boolean should be named isFoo, hasFoo, areFoo")
+ if is_get(m):
+ if re.match("is[A-Z]", m.name):
+ target = m.name[2:]
+ expected = "setIs" + target
+ error_if_exists(sets, m.name, expected, "setHas" + target)
+ elif re.match("has[A-Z]", m.name):
+ target = m.name[3:]
+ expected = "setHas" + target
+ error_if_exists(sets, m.name, expected, "setIs" + target)
+ error_if_exists(sets, m.name, expected, "set" + target)
+ elif re.match("get[A-Z]", m.name):
+ target = m.name[3:]
+ expected = "set" + target
+ error_if_exists(sets, m.name, expected, "setIs" + target)
+ error_if_exists(sets, m.name, expected, "setHas" + target)
+
+ if is_set(m):
+ if re.match("set[A-Z]", m.name):
+ target = m.name[3:]
+ expected = "get" + target
+ error_if_exists(sets, m.name, expected, "is" + target)
+ error_if_exists(sets, m.name, expected, "has" + target)
def verify_collections(clazz):
@@ -674,10 +692,10 @@
"java.util.HashMap", "java.util.HashSet", "android.util.ArraySet", "android.util.ArrayMap"]
for m in clazz.methods:
if m.typ in bad:
- error(clazz, m, "CL2", "Return type is concrete collection; should be interface")
+ error(clazz, m, "CL2", "Return type is concrete collection; must be higher-level interface")
for arg in m.args:
if arg in bad:
- error(clazz, m, "CL2", "Argument is concrete collection; should be interface")
+ error(clazz, m, "CL2", "Argument is concrete collection; must be higher-level interface")
def verify_flags(clazz):
@@ -740,7 +758,7 @@
if not clazz.name.endswith("Manager"): return
for c in clazz.ctors:
- error(clazz, c, None, "Managers should always be obtained from Context")
+ error(clazz, c, None, "Managers must always be obtained from Context")
def verify_boxed(clazz):
@@ -751,18 +769,18 @@
for c in clazz.ctors:
for arg in c.args:
if arg in boxed:
- error(clazz, c, None, "Must avoid boxed primitives")
+ error(clazz, c, "M11", "Must avoid boxed primitives")
for f in clazz.fields:
if f.typ in boxed:
- error(clazz, f, None, "Must avoid boxed primitives")
+ error(clazz, f, "M11", "Must avoid boxed primitives")
for m in clazz.methods:
if m.typ in boxed:
- error(clazz, m, None, "Must avoid boxed primitives")
+ error(clazz, m, "M11", "Must avoid boxed primitives")
for arg in m.args:
if arg in boxed:
- error(clazz, m, None, "Must avoid boxed primitives")
+ error(clazz, m, "M11", "Must avoid boxed primitives")
def verify_static_utils(clazz):
@@ -875,20 +893,56 @@
if "android.os.Handler" in m.args:
takes_handler = True
if not takes_handler:
- error(clazz, f, "L1", "Registration methods should have overload that accepts delivery Handler")
+ warn(clazz, f, "L1", "Registration methods should have overload that accepts delivery Handler")
def verify_context_first(clazz):
"""Verifies that methods accepting a Context keep it the first argument."""
- for m in clazz.ctors:
- if len(m.args) > 1:
+ examine = clazz.ctors + clazz.methods
+ for m in examine:
+ if len(m.args) > 1 and m.args[0] != "android.content.Context":
if "android.content.Context" in m.args[1:]:
error(clazz, m, "M3", "Context is distinct, so it must be the first argument")
- for m in clazz.methods:
- if len(m.args) > 1:
- if "android.content.Context" in m.args[1:]:
- error(clazz, m, "M3", "Context is distinct, so it must be the first argument")
+
+def verify_listener_last(clazz):
+ """Verifies that methods accepting a Listener or Callback keep them as last arguments."""
+ examine = clazz.ctors + clazz.methods
+ for m in examine:
+ if "Listener" in m.name or "Callback" in m.name: continue
+ found = False
+ for a in m.args:
+ if a.endswith("Callback") or a.endswith("Callbacks") or a.endswith("Listener"):
+ found = True
+ elif found and a != "android.os.Handler":
+ warn(clazz, m, "M3", "Listeners should always be at end of argument list")
+
+
+def verify_resource_names(clazz):
+ """Verifies that resource names have consistent case."""
+ if not re.match("android\.R\.[a-z]+", clazz.fullname): return
+
+ # Resources defined by files are foo_bar_baz
+ if clazz.name in ["anim","animator","color","dimen","drawable","interpolator","layout","transition","menu","mipmap","string","plurals","raw","xml"]:
+ for f in clazz.fields:
+ if re.match("[a-z1-9_]+$", f.name): continue
+ error(clazz, f, None, "Expected resource name in this class to be foo_bar_baz style")
+
+ # Resources defined inside files are fooBarBaz
+ if clazz.name in ["array","attr","id","bool","fraction","integer"]:
+ for f in clazz.fields:
+ if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue
+ if re.match("layout_[a-z][a-zA-Z1-9]*$", f.name): continue
+ if re.match("state_[a-z_]*$", f.name): continue
+
+ if re.match("[a-z][a-zA-Z1-9]*$", f.name): continue
+ error(clazz, f, "C7", "Expected resource name in this class to be fooBarBaz style")
+
+ # Styles are FooBar_Baz
+ if clazz.name in ["style"]:
+ for f in clazz.fields:
+ if re.match("[A-Z][A-Za-z1-9]+(_[A-Z][A-Za-z1-9]+?)*$", f.name): continue
+ error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
def verify_style(api):
@@ -938,6 +992,8 @@
verify_overload_args(clazz)
verify_callback_handlers(clazz)
verify_context_first(clazz)
+ verify_listener_last(clazz)
+ verify_resource_names(clazz)
return failures