Merge changes Ib2def344,Ifd15736b
* changes:
Permit layout when stopped if reporting draw
Refactor computeScreenConfigurationLocked and more.
diff --git a/api/current.txt b/api/current.txt
index 7d8b892..a1cdc8d 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
}
@@ -28745,6 +28747,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 6968896..13a8981 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
}
@@ -15118,6 +15120,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 +30867,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/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/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/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/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/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/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/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/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/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/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/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/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 cfff420..8814138 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2634,4 +2634,9 @@
<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/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index 1a92753..75f541a 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -536,7 +536,7 @@
</p>
<p> For more information about using the mipmap folders, see
-<a href="{@docRoot}tools/project/index.html#mipmap">Managing Projects Overview</a>.</p>
+<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>
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/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 7c963dd..b6f1c49 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -368,7 +368,7 @@
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/project/index.html#mipmap">Managing Projects Overview</a>.
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.
</p>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 98e7c96..fc79970 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -76,7 +76,7 @@
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/project/index.html#mipmap">Managing Projects Overview</a>.</p>
+<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>
diff --git a/docs/html/images/tools/studio-inspections-config.png b/docs/html/images/tools/studio-inspections-config.png
new file mode 100644
index 0000000..e41afa1
--- /dev/null
+++ b/docs/html/images/tools/studio-inspections-config.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/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/studio/index.jd b/docs/html/tools/studio/index.jd
index 26fe3cd..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/"
@@ -244,7 +244,7 @@
-<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
@@ -255,33 +255,81 @@
-<h3> Lint inspections</h3>
-<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. Choose the <strong>Analyze >
-Inspect Code</strong> to manually run the inspections. The {@code lint} settings icon in the
-Inspection display provides a complete list of the current inspections.</p>
+<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>Hovering over a Lint error displays the full issue explanation inline for easy error
+
+<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
+ base name as the class name.</li>
+ <li>Security check for fragment injection.</li>
+ <li>Where ever property assignment no longer works as expected.</li>
+ <li>Gradle plugin version is compatible with the SDK.</li>
+ <li>Right to left validation </li>
+ <li>Required API version</li>
+ <li>many others</li>
+</ul>
+
+
+<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>
@@ -346,6 +394,7 @@
<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 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>
@@ -519,7 +568,8 @@
<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 13.</strong> Code Sample Access</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 1fc5904..64e70fd 100644
--- a/docs/html/training/multiscreen/screendensities.jd
+++ b/docs/html/training/multiscreen/screendensities.jd
@@ -154,7 +154,7 @@
<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/project/index.html#mipmap">Managing Projects Overview</a>.</p>
+<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
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/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/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/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/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/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/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 78f6ace..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.
*
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/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0420d35..808ded5 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -483,17 +483,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/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/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/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 885465b..e238d30 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -177,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;
@@ -3930,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
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/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7ff7827..8170835 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);
@@ -4215,12 +4167,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 +4186,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 +4205,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 +4224,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 +4242,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 +4296,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 +4319,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 +4344,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 +4416,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 +4461,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 +4566,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 +4609,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 +4682,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 +4734,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 +4749,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 +4771,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 +4788,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 +4893,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 +4914,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 +4935,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 +4977,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 +5045,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 +5084,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 +5133,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 +5149,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 +5171,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 +5197,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 +5259,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 +5280,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 +5309,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 +5327,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/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/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