Merge "Fix issue #21814207 and issue #21814212 (alarm manager)" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index ca8cb8c..b72730a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -826,6 +826,7 @@
field public static final int listViewWhiteStyle = 16842869; // 0x1010075
field public static final int lockTaskMode = 16844015; // 0x10104ef
field public static final int logo = 16843454; // 0x10102be
+ field public static final int logoDescription = 16844026; // 0x10104fa
field public static final int longClickable = 16842982; // 0x10100e6
field public static final int loopViews = 16843527; // 0x1010307
field public static final int manageSpaceActivity = 16842756; // 0x1010004
@@ -1178,6 +1179,7 @@
field public static final int submitBackground = 16843912; // 0x1010488
field public static final int subtitle = 16843473; // 0x10102d1
field public static final int subtitleTextAppearance = 16843823; // 0x101042f
+ field public static final int subtitleTextColor = 16844028; // 0x10104fc
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1308,6 +1310,7 @@
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
field public static final int titleTextAppearance = 16843822; // 0x101042e
+ field public static final int titleTextColor = 16844027; // 0x10104fb
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
@@ -12303,7 +12306,6 @@
method public android.graphics.drawable.Drawable.ConstantState getConstantState();
method public android.graphics.drawable.Drawable getCurrent();
method public android.graphics.Rect getDirtyBounds();
- method public boolean getDither();
method public void getHotspotBounds(android.graphics.Rect);
method public int getIntrinsicHeight();
method public int getIntrinsicWidth();
@@ -12320,6 +12322,7 @@
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void invalidateSelf();
method public boolean isAutoMirrored();
+ method public boolean isDither();
method public boolean isFilterBitmap();
method public boolean isStateful();
method public final boolean isVisible();
@@ -28910,6 +28913,7 @@
method public void onDestroy();
method public boolean[] onGetSupportedCommands(java.lang.String[]);
method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
+ method public void onHandleScreenshot(android.graphics.Bitmap);
method public void onHide();
method public boolean onKeyDown(int, android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
@@ -28932,6 +28936,7 @@
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
field public static final int SHOW_WITH_ASSIST = 1; // 0x1
+ field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2
}
public static final class VoiceInteractionSession.AbortVoiceRequest extends android.service.voice.VoiceInteractionSession.Request {
@@ -30620,10 +30625,14 @@
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+ field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_vibration_bool";
+ field public static final java.lang.String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
diff --git a/api/system-current.txt b/api/system-current.txt
index fe8a21e..e328920 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -901,6 +901,7 @@
field public static final int listViewWhiteStyle = 16842869; // 0x1010075
field public static final int lockTaskMode = 16844015; // 0x10104ef
field public static final int logo = 16843454; // 0x10102be
+ field public static final int logoDescription = 16844026; // 0x10104fa
field public static final int longClickable = 16842982; // 0x10100e6
field public static final int loopViews = 16843527; // 0x1010307
field public static final int manageSpaceActivity = 16842756; // 0x1010004
@@ -1257,6 +1258,7 @@
field public static final int submitBackground = 16843912; // 0x1010488
field public static final int subtitle = 16843473; // 0x10102d1
field public static final int subtitleTextAppearance = 16843823; // 0x101042f
+ field public static final int subtitleTextColor = 16844028; // 0x10104fc
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1387,6 +1389,7 @@
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
field public static final int titleTextAppearance = 16843822; // 0x101042e
+ field public static final int titleTextColor = 16844027; // 0x10104fb
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
@@ -12628,7 +12631,6 @@
method public android.graphics.drawable.Drawable.ConstantState getConstantState();
method public android.graphics.drawable.Drawable getCurrent();
method public android.graphics.Rect getDirtyBounds();
- method public boolean getDither();
method public void getHotspotBounds(android.graphics.Rect);
method public int getIntrinsicHeight();
method public int getIntrinsicWidth();
@@ -12645,6 +12647,7 @@
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void invalidateSelf();
method public boolean isAutoMirrored();
+ method public boolean isDither();
method public boolean isFilterBitmap();
method public boolean isStateful();
method public final boolean isVisible();
@@ -31057,6 +31060,7 @@
method public void onDestroy();
method public boolean[] onGetSupportedCommands(java.lang.String[]);
method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
+ method public void onHandleScreenshot(android.graphics.Bitmap);
method public void onHide();
method public boolean onKeyDown(int, android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
@@ -31079,6 +31083,7 @@
method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
field public static final int SHOW_WITH_ASSIST = 1; // 0x1
+ field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2
}
public static final class VoiceInteractionSession.AbortVoiceRequest extends android.service.voice.VoiceInteractionSession.Request {
@@ -32850,10 +32855,14 @@
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+ field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_vibration_bool";
+ field public static final java.lang.String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
+ field public static final java.lang.String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
field public static final java.lang.String KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL = "has_in_call_noise_suppression_bool";
field public static final java.lang.String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
field public static final java.lang.String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
index d461bca..1aee794 100644
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
@@ -138,8 +138,8 @@
* errors, then add them to the top switch statement
*/
if (errorFlag < 0) {
- throw new UnsupportedOperationException(String.format("Unknown error %d",
- errorFlag));
+ throw new CameraRuntimeException(CAMERA_ERROR,
+ String.format("Unknown camera device error %d", errorFlag));
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index d5ee7e7..0367cfc 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -80,7 +80,6 @@
public static final int SHOW_WITH_ASSIST = 1<<0;
/**
- * @hide
* Flag received in {@link #onShow}: originator requested that the session be started with
* a screen shot of the currently focused activity.
*/
@@ -1162,7 +1161,6 @@
onHandleAssist(data);
}
- /** @hide */
public void onHandleScreenshot(Bitmap screenshot) {
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index affc5da..339038e 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -522,7 +522,7 @@
View baselineView = null;
LayoutParams baselineParams = null;
for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
final LayoutParams childParams = (LayoutParams) child.getLayoutParams();
if (baselineView == null || baselineParams == null
@@ -548,9 +548,9 @@
if (offsetHorizontalAxis) {
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
final int[] rules = params.getRules(layoutDirection);
if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
centerHorizontal(child, params, width);
@@ -578,9 +578,9 @@
if (offsetVerticalAxis) {
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
final int[] rules = params.getRules(layoutDirection);
if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
centerVertical(child, params, height);
@@ -607,9 +607,9 @@
final int verticalOffset = contentBounds.top - top;
if (horizontalOffset != 0 || verticalOffset != 0) {
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE && child != ignore) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
if (horizontalGravity) {
params.mLeft += horizontalOffset;
params.mRight += horizontalOffset;
@@ -626,9 +626,9 @@
if (isLayoutRtl()) {
final int offsetWidth = myWidth - width;
for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
+ final View child = views[i];
if (child.getVisibility() != GONE) {
- LayoutParams params = (LayoutParams) child.getLayoutParams();
+ final LayoutParams params = (LayoutParams) child.getLayoutParams();
params.mLeft -= offsetWidth;
params.mRight -= offsetWidth;
}
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 2ea2667..471ea9b 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -273,6 +273,24 @@
if (!TextUtils.isEmpty(navDesc)) {
setNavigationContentDescription(navDesc);
}
+
+ final Drawable logo = a.getDrawable(R.styleable.Toolbar_logo);
+ if (logo != null) {
+ setLogo(logo);
+ }
+
+ final CharSequence logoDesc = a.getText(R.styleable.Toolbar_logoDescription);
+ if (!TextUtils.isEmpty(logoDesc)) {
+ setLogoDescription(logoDesc);
+ }
+
+ if (a.hasValue(R.styleable.Toolbar_titleTextColor)) {
+ setTitleTextColor(a.getColor(R.styleable.Toolbar_titleTextColor, 0xffffffff));
+ }
+
+ if (a.hasValue(R.styleable.Toolbar_subtitleTextColor)) {
+ setSubtitleTextColor(a.getColor(R.styleable.Toolbar_subtitleTextColor, 0xffffffff));
+ }
a.recycle();
}
diff --git a/core/res/res/drawable/spinner_background_material.xml b/core/res/res/drawable/spinner_background_material.xml
index 892dbc5..d37f5b7 100644
--- a/core/res/res/drawable/spinner_background_material.xml
+++ b/core/res/res/drawable/spinner_background_material.xml
@@ -17,22 +17,18 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack"
android:paddingStart="0dp"
- android:paddingEnd="48dp"
+ android:paddingEnd="24dp"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<item
android:gravity="end|center_vertical"
- android:width="48dp"
- android:height="48dp">
- <ripple
- android:color="?attr/colorControlHighlight"
- android:radius="24dp" />
- </item>
+ android:width="24dp"
+ android:height="24dp"
+ android:drawable="@drawable/control_background_40dp_material" />
<item
android:drawable="@drawable/ic_spinner_caret"
android:gravity="end|center_vertical"
android:width="24dp"
- android:height="24dp"
- android:end="12dp" />
+ android:height="24dp" />
</layer-list>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c08d511..647dde7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7775,6 +7775,16 @@
<!-- Text to set as the content description for the navigation button
located at the start of the toolbar. -->
<attr name="navigationContentDescription" format="string" />
+ <!-- Drawable to set as the logo that appears at the starting side of
+ the Toolbar, just after the navigation button. -->
+ <attr name="logo" />
+ <!-- A content description string to describe the appearance of the
+ associated logo image. -->
+ <attr name="logoDescription" format="string" />
+ <!-- A color to apply to the title string. -->
+ <attr name="titleTextColor" format="color" />
+ <!-- A color to apply to the subtitle string. -->
+ <attr name="subtitleTextColor" format="color" />
</declare-styleable>
<declare-styleable name="Toolbar_LayoutParams">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bbe27a4..b7f4724 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2699,4 +2699,7 @@
<public type="attr" name="scrollIndicators" />
<public type="attr" name="hyphenationFrequency" />
<public type="attr" name="fingerprintAuthDrawable" />
+ <public type="attr" name="logoDescription" />
+ <public type="attr" name="titleTextColor" />
+ <public type="attr" name="subtitleTextColor" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 510f6a5..ea0d349 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -537,10 +537,10 @@
<!-- Label for the Android system components when they are shown to the user. -->
<string name="android_system_label">Android System</string>
- <!-- Label for the user owner in the intent forwarding app. -->
- <string name="user_owner_label">Personal apps</string>
+ <!-- Label for the user owner in the intent forwarding app. [CHAR LIMIT=15] -->
+ <string name="user_owner_label">Personal</string>
- <!-- Label for a corporate profile in the intent forwarding app. -->
+ <!-- Label for a corporate profile in the intent forwarding app. [CHAR LIMIT=15] -->
<string name="managed_profile_label">Work</string>
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd
index fca958e..52cb13e 100644
--- a/docs/html/training/articles/keystore.jd
+++ b/docs/html/training/articles/keystore.jd
@@ -32,7 +32,7 @@
keystore, they can be used for cryptographic operations with the key material
remaining non-exportable. Moreover, it offers facilities to restrict when and
how keys can be used, such as requiring user authentication for key use or
- restricting encryption keys to be used only in certain block modes. See
+ restricting keys to be used only in certain cryptographic modes. See
<a href="#SecurityFeatures">Security Features</a> section for more information.</p>
<p>The Keystore system is used by the {@link
@@ -48,7 +48,8 @@
mitigates unauthorized use of key material outside of the Android device by preventing extraction of
the key material from application processes and from the Android device as a whole. Secondly,
Android KeyStore mitigates unauthorized use of key material on the Android device by making apps
-specify authorized uses of their keys and then enforcing these restrictions.
+specify authorized uses of their keys and then enforcing these restrictions outside of the apps'
+processes.
<h3 id="ExtractionPrevention">Extraction Prevention</h3>
@@ -78,14 +79,16 @@
To mitigate unauthorized use of keys on the Android device, Android Keystore lets apps specify
authorized uses of their keys when generating or importing the keys. Once a key is generated or
imported, its authorizations can not be changed. Authorizations are then enforced by the Android
-Keystore whenever the key is used.
+Keystore whenever the key is used. This is an advanced security feature which is generally useful
+only if your requirements are that a compromise of your application process after key
+generation/import (but not before or during) cannot lead to unauthorized uses of the key.
<p>Supported key use authorizations fall into the following categories:
<ul>
<li><em>cryptography</em>: authorized key algorithm, operations or purposes (encrypt, decrypt, sign,
- verify), padding schemes, block modes, digests with which the key can be used</li>
+ verify), padding schemes, block modes, digests with which the key can be used;</li>
<li><em>temporal validity interval</em>: interval of time during which the key is authorized for
- use</li>
+ use;</li>
<li><em>user authentication</em>: the key can only be used if the user has been authenticated
recently enough. See <a href="#UserAuthentication">Requiring User Authentication For Key Use</a>.
</li>
@@ -181,23 +184,33 @@
<h3 id="UserAuthentication">Requiring User Authentication For Key Use</h3>
<p>When generating or importing a key into the {@code AndroidKeyStore} you can specify that the key
-can only be used if user has been authenticated. The user is authenticated using a subset of their
-secure lock screen credentials. This is a security measure which makes it possible to generate
-cryptographic assertions about the user having been authenticated.
+is only authorized to be used if the user has been authenticated. The user is authenticated using a
+subset of their secure lock screen credentials (pattern/PIN/password, fingerprint).
-<p>When a key is configured to require user authentication, it is also configured to operate in one
-of the two modes:
+<p>This is an advanced security feature which is generally useful only if your requirements are that
+a compromise of your application process after key generation/import (but not before or during)
+cannot bypass the requirement for the user to be authenticated to use the key.
+
+<p>When a key is authorized to be used only if the user has been authenticated, it is configured to
+operate in one of the two modes:
<ul>
-<li>User authentication is valid for a duration of time. All keys in this mode are authorized
- for use as soon as the user unlocks the secure lock screen or confirms their secure lock screen
- credentials using the {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence) KeyguardManager.createConfirmDeviceCredentialIntent}
- flow. Each key specifies for how long the authorization remains valid for that key. Such keys
- can only be generated or imported if the secure lock screen is enabled (see {@link android.app.KeyguardManager#isDeviceSecure() KeyguardManager.isDeviceSecure()}).
- These keys become permanently invalidated once the secure lock screen is disabled or forcibly
- reset (e.g. by a Device Admin).</li>
-<li>User authentication is required for every use of the key. In this mode, a specific operation
- involving a specific key is authorized by the user. Currently, the only means of such
- authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, int, AuthenticationCallback, Handler) FingerprintManager.authenticate}.
- Such keys can only be generated or imported if at least one fingerprint is enrolled (see {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}).
- These keys become permanently invalidated once all fingerprints are unenrolled.</li>
-</ul>
+<li>User authentication authorizes the use of keys for a duration of time. All keys in this mode are
+ authorized for use as soon as the user unlocks the secure lock screen or confirms their secure
+ lock screen credential using the
+ {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence) KeyguardManager.createConfirmDeviceCredentialIntent}
+ flow. The duration for which the authorization remains valid is specific to each key, as specified
+ using {@code setUserAuthenticationValidityDurationSeconds} during key generation or import. Such
+ keys can only be generated or imported if the secure lock screen is enabled (see
+ {@link android.app.KeyguardManager#isDeviceSecure() KeyguardManager.isDeviceSecure()}). These keys
+ become permanently invalidated once the secure lock screen is disabled (reconfigured to None,
+ Swipe or other mode which does not authenticate the user) or forcibly reset (e.g. by a Device
+ Administrator).</li>
+<li>User authentication authorizes a specific cryptographic operation associated with one key. In
+ this mode, each operation involving such a key must be individually authorized by the user.
+ Currently, the only means of such authorization is fingerprint authentication:
+ {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, int, AuthenticationCallback, Handler) FingerprintManager.authenticate}.
+ Such keys can only be generated or imported if at least one fingerprint is enrolled (see
+ {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}).
+ These keys become permanently invalidated once a new fingerprint is enrolled or all fingerprints
+ are unenrolled.</li>
+</ul>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index a0c407f..f059727 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -363,7 +363,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mBitmapState.mPaint.isDither();
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 415af0d..6090cf0 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -279,7 +279,7 @@
* @return whether this drawable dithers its colors
* @see #setDither(boolean)
*/
- public boolean getDither() {
+ public boolean isDither() {
return false;
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 8b801c3..1759f53 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,7 +167,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mDrawableContainerState.mDither;
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index ed47eed..626991d 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -826,7 +826,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mGradientState.mDither;
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 5c00a23..90891f6 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -1248,12 +1248,12 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
final Drawable dr = getFirstNonNullDrawable();
if (dr != null) {
- return dr.getDither();
+ return dr.isDither();
} else {
- return super.getDither();
+ return super.isDither();
}
}
@@ -1537,8 +1537,23 @@
continue;
}
+ // Take the resolved layout direction into account. If start / end
+ // padding are defined, they will be resolved (hence overriding) to
+ // left / right or right / left depending on the resolved layout
+ // direction. If start / end padding are not defined, use the
+ // left / right ones.
+ final int insetL, insetR;
+ final int layoutDirection = getLayoutDirection();
+ if (layoutDirection == LayoutDirection.RTL) {
+ insetL = r.mInsetE == UNDEFINED_INSET ? r.mInsetL : r.mInsetE;
+ insetR = r.mInsetS == UNDEFINED_INSET ? r.mInsetR : r.mInsetS;
+ } else {
+ insetL = r.mInsetS == UNDEFINED_INSET ? r.mInsetL : r.mInsetS;
+ insetR = r.mInsetE == UNDEFINED_INSET ? r.mInsetR : r.mInsetE;
+ }
+
final int minWidth = r.mWidth < 0 ? r.mDrawable.getIntrinsicWidth() : r.mWidth;
- final int w = minWidth + r.mInsetL + r.mInsetR + padL + padR;
+ final int w = minWidth + insetL + insetR + padL + padR;
if (w > width) {
width = w;
}
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 0b7869b..adf53e3 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -374,7 +374,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mPaint == null ? DEFAULT_DITHER : mPaint.isDither();
}
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 334b3bd..a669d3c 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -328,7 +328,7 @@
}
@Override
- public boolean getDither() {
+ public boolean isDither() {
return mShapeState.mPaint.isDither();
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index af05578..2055cdb 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -226,9 +226,8 @@
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
specBuilder.setDigests(KeyProperties.DIGEST_NONE);
- specBuilder.setSignaturePaddings(
- KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
- // Authorized to be used with any padding (including no padding).
+ // Authorized to be used with any encryption and signature padding
+ // scheme (including no padding).
specBuilder.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_NONE);
// Disable randomized encryption requirement to support encryption
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 3bd9d1d..5fb589e 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -258,9 +258,8 @@
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
specBuilder.setDigests(KeyProperties.DIGEST_NONE);
- specBuilder.setSignaturePaddings(
- KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
- // Authorized to be used with any padding (including no padding).
+ // Authorized to be used with any encryption and signature padding scheme (including no
+ // padding).
specBuilder.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_NONE);
// Disable randomized encryption requirement to support encryption padding NONE
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 8d4bfcd..1732db9 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -19,16 +19,20 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.KeyguardManager;
+import android.hardware.fingerprint.FingerprintManager;
import android.text.TextUtils;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
+import java.security.Signature;
import java.security.cert.Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Date;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
import javax.security.auth.x500.X500Principal;
/**
@@ -62,10 +66,15 @@
* <p>NOTE: If a private key is not authorized to sign the self-signed certificate, then the
* certificate will be created with an invalid signature which will not verify. Such a certificate
* is still useful because it provides access to the public key. To generate a valid
- * signature for the certificate the key needs to be authorized for
- * {@link KeyProperties#PURPOSE_SIGN}, a suitable digest or {@link KeyProperties#DIGEST_NONE}, and
- * {@link KeyProperties#SIGNATURE_PADDING_RSA_PKCS1} or
- * {@link KeyProperties#ENCRYPTION_PADDING_NONE}.
+ * signature for the certificate the key needs to be authorized for all of the following:
+ * <ul>
+ * <li>{@link KeyProperties#PURPOSE_SIGN},</li>
+ * <li>operation without requiring the user to be authenticated (see
+ * {@link Builder#setUserAuthenticationRequired(boolean)}),</li>
+ * <li>suitable digest or {@link KeyProperties#DIGEST_NONE},</li>
+ * <li>(RSA keys only) padding scheme {@link KeyProperties#SIGNATURE_PADDING_RSA_PKCS1} or
+ * {@link KeyProperties#ENCRYPTION_PADDING_NONE}.</li>
+ * </ul>
*
* <p>NOTE: The key material of the generated symmetric and private keys is not accessible. The key
* material of the public keys is accessible.
@@ -103,7 +112,7 @@
*
* <p><h3>Example: Symmetric key</h3>
* The following example illustrates how to generate an AES key in the Android KeyStore system under
- * alias {@code key2} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
+ * alias {@code key2} authorized to be used only for encryption/decryption in GCM mode with no
* padding.
* <pre> {@code
* KeyGenerator keyGenerator = KeyGenerator.getInstance(
@@ -112,8 +121,8 @@
* keyGenerator.initialize(
* new KeyGenParameterSpec.Builder("key2",
* KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- * .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
- * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+ * .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
* .build());
* SecretKey key = keyGenerator.generateKey();
*
@@ -368,7 +377,7 @@
}
/**
- * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+ * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
* when encrypting/decrypting. Attempts to use the key with any other block modes will be
* rejected.
*
@@ -393,28 +402,32 @@
}
/**
- * Returns {@code true} if user authentication is required for this key to be used.
+ * Returns {@code true} if the key is authorized to be used only if the user has been
+ * authenticated.
*
- * <p>This restriction applies only to private key operations. Public key operations are not
- * restricted.
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setUserAuthenticationRequired(boolean)
*/
public boolean isUserAuthenticationRequired() {
return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Gets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect only if user authentication is required
+ * (see {@link #isUserAuthenticationRequired()}).
*
- * <p>This restriction applies only to private key operations. Public key operations are not
- * restricted.
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @return duration in seconds or {@code -1} if authentication is required for every use of the
- * key.
+ * key.
*
* @see #isUserAuthenticationRequired()
+ * @see Builder#setUserAuthenticationValidityDurationSeconds(int)
*/
public int getUserAuthenticationValidityDurationSeconds() {
return mUserAuthenticationValidityDurationSeconds;
@@ -681,11 +694,11 @@
}
/**
- * Sets the set of block modes (e.g., {@code CBC}, {@code CTR}, {@code ECB}) with which the
- * key can be used when encrypting/decrypting. Attempts to use the key with any other block
- * modes will be rejected.
+ * Sets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be
+ * used when encrypting/decrypting. Attempts to use the key with any other block modes will
+ * be rejected.
*
- * <p>This must be specified for encryption/decryption keys.
+ * <p>This must be specified for symmetric encryption/decryption keys.
*
* <p>See {@link KeyProperties}.{@code BLOCK_MODE} constants.
*/
@@ -711,7 +724,7 @@
* <li>encryption/decryption transformation which do not offer {@code IND-CPA}, such as
* {@code ECB} with a symmetric encryption algorithm, or RSA encryption/decryption without
* padding, are prohibited;</li>
- * <li>in block modes which use an IV, such as {@code CBC}, {@code CTR}, and {@code GCM},
+ * <li>in block modes which use an IV, such as {@code GCM}, {@code CBC}, and {@code CTR},
* caller-provided IVs are rejected when encrypting, to ensure that only random IVs are
* used.</li>
* </ul>
@@ -738,22 +751,38 @@
}
/**
- * Sets whether user authentication is required to use this key.
+ * Sets whether this key is authorized to be used only if the user has been authenticated.
*
- * <p>By default, the key can be used without user authentication.
+ * <p>By default, the key is authorized to be used regardless of whether the user has been
+ * authenticated.
*
- * <p>When user authentication is required, the user authorizes the use of the key by
- * authenticating to this Android device using a subset of their secure lock screen
- * credentials. Different authentication methods are used depending on whether the every
- * use of the key must be authenticated (as specified by
- * {@link #setUserAuthenticationValidityDurationSeconds(int)}).
+ * <p>When user authentication is required:
+ * <ul>
+ * <li>The key can only be generated if secure lock screen is set up (see
+ * {@link KeyguardManager#isDeviceSecure()}). Additionally, if the key requires that user
+ * authentication takes place for every use of the key (see
+ * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one fingerprint
+ * must be enrolled (see {@link FingerprintManager#hasEnrolledFingerprints()}).</li>
+ * <li>The use of the key must be authorized by the user by authenticating to this Android
+ * device using a subset of their secure lock screen credentials such as
+ * password/PIN/pattern or fingerprint.
* <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
* information</a>.
+ * <li>The key will become <em>irreversibly invalidated</em> once the secure lock screen is
+ * disabled (reconfigured to None, Swipe or other mode which does not authenticate the user)
+ * or when the secure lock screen is forcibly reset (e.g., by a Device Administrator).
+ * Additionally, if the key requires that user authentication takes place for every use of
+ * the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\
+ * no more fingerprints are enrolled. Attempts to initialize cryptographic operations using
+ * such keys will throw {@link KeyPermanentlyInvalidatedException}.</li>
+ * </ul>
*
- * <p>This restriction applies only to private key operations. Public key operations are not
- * restricted.
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #setUserAuthenticationValidityDurationSeconds(int)
+ * @see KeyguardManager#isDeviceSecure()
+ * @see FingerprintManager#hasEnrolledFingerprints()
*/
@NonNull
public Builder setUserAuthenticationRequired(boolean required) {
@@ -762,15 +791,39 @@
}
/**
- * Sets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Sets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect if the key requires user
+ * authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
*
- * <p>By default, the user needs to authenticate for every use of the key.
+ * <p>By default, if user authentication is required, it must take place for every use of
+ * the key.
*
- * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
- * every use of the key.
+ * <p>Cryptographic operations involving keys which require user authentication to take
+ * place for every operation can only use fingerprint authentication. This is achieved by
+ * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac})
+ * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking
+ * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with
+ * the cryptographic operation only if the authentication flow succeeds.
+ *
+ * <p>Cryptographic operations involving keys which are authorized to be used for a duration
+ * of time after a successful user authentication event can only use secure lock screen
+ * authentication. These cryptographic operations will throw
+ * {@link UserNotAuthenticatedException} during initialization if the user needs to be
+ * authenticated to proceed. This situation can be resolved by the user unlocking the secure
+ * lock screen of the Android or by going through the confirm credential flow initiated by
+ * {@link KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence)}.
+ * Once resolved, initializing a new cryptographic operation using this key (or any other
+ * key which is authorized to be used for a fixed duration of time after user
+ * authentication) should succeed provided the user authentication flow completed
+ * successfully.
+ *
+ * @param seconds duration in seconds or {@code -1} if user authentication must take place
+ * for every use of the key.
*
* @see #setUserAuthenticationRequired(boolean)
+ * @see FingerprintManager
+ * @see FingerprintManager.CryptoObject
+ * @see KeyguardManager
*/
@NonNull
public Builder setUserAuthenticationValidityDurationSeconds(
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index 03b4100..785ec15 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -30,7 +30,7 @@
* Keystore system</a>. This class describes whether the key material is available in
* plaintext outside of secure hardware, whether user authentication is required for using the key
* and whether this requirement is enforced by secure hardware, the key's origin, what uses the key
- * is authorized for (e.g., only in {@code CBC} mode, or signing only), whether the key should be
+ * is authorized for (e.g., only in {@code GCM} mode, or signing only), whether the key should be
* encrypted at rest, the key's and validity start and end dates.
*
* <p>Instances of this class are immutable.
@@ -191,7 +191,7 @@
}
/**
- * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+ * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
* when encrypting/decrypting. Attempts to use the key with any other block modes will be
* rejected.
*
@@ -238,17 +238,27 @@
}
/**
- * Returns {@code true} if user authentication is required for this key to be used.
+ * Returns {@code true} if the key is authorized to be used only if the user has been
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #getUserAuthenticationValidityDurationSeconds()
+ * @see KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)
+ * @see KeyProtection.Builder#setUserAuthenticationRequired(boolean)
*/
public boolean isUserAuthenticationRequired() {
return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Gets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect only if user authentication is required
+ * (see {@link #isUserAuthenticationRequired()}).
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @return duration in seconds or {@code -1} if authentication is required for every use of the
* key.
diff --git a/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java b/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java
index e320c9c..9e82fc0 100644
--- a/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java
+++ b/keystore/java/android/security/keystore/KeyPermanentlyInvalidatedException.java
@@ -21,12 +21,13 @@
/**
* Indicates that the key can no longer be used because it has been permanently invalidated.
*
- * <p>This can currently occur only for keys that require user authentication. Such keys are
- * permanently invalidated once the secure lock screen is disabled (i.e., reconfigured to None,
- * Swipe or other mode which does not authenticate the user) or when the secure lock screen is
- * forcibly reset (e.g., by Device Admin). Additionally, keys configured to require user
- * authentication for every use of the key are also permanently invalidated once a new fingerprint
- * is enrolled or once no more fingerprints are enrolled.
+ * <p>This only occurs for keys which are authorized to be used only if the user has been
+ * authenticated. Such keys are permanently and irreversibly invalidated once the secure lock screen
+ * is disabled (i.e., reconfigured to None, Swipe or other mode which does not authenticate the
+ * user) or when the secure lock screen is forcibly reset (e.g., by Device Admin). Additionally,
+ * keys configured to require user authentication to take place for every of the keys, are also
+ * permanently invalidated once a new fingerprint is enrolled or once no more fingerprints are
+ * enrolled.
*/
public class KeyPermanentlyInvalidatedException extends InvalidKeyException {
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 1e0611c..b7a2a0b 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -19,19 +19,23 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.KeyguardManager;
+import android.hardware.fingerprint.FingerprintManager;
import java.security.Key;
+import java.security.Signature;
import java.security.KeyStore.ProtectionParameter;
import java.security.cert.Certificate;
import java.util.Date;
import javax.crypto.Cipher;
+import javax.crypto.Mac;
/**
* Specification of how a key or key pair is secured when imported into the
* <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. This class
* specifies parameters such as whether user authentication is required for using the key, what uses
- * the key is authorized for (e.g., only in {@code CTR} mode, or only for signing -- decryption not
+ * the key is authorized for (e.g., only in {@code GCM} mode, or only for signing -- decryption not
* permitted), the key's and validity start and end dates.
*
* <p>To import a key or key pair into the Android KeyStore, create an instance of this class using
@@ -51,8 +55,8 @@
*
* <p><h3>Example: Symmetric Key</h3>
* The following example illustrates how to import an AES key into the Android KeyStore under alias
- * {@code key1} authorized to be used only for encryption/decryption in CBC mode with PKCS#7
- * padding. The key must export its key material via {@link Key#getEncoded()} in {@code RAW} format.
+ * {@code key1} authorized to be used only for encryption/decryption in GCM mode with no padding.
+ * The key must export its key material via {@link Key#getEncoded()} in {@code RAW} format.
* <pre> {@code
* SecretKey key = ...; // AES key
*
@@ -62,8 +66,8 @@
* "key1",
* new KeyStore.SecretKeyEntry(key),
* new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
- * .setBlockMode(KeyProperties.BLOCK_MODE_CBC)
- * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
+ * .setBlockMode(KeyProperties.BLOCK_MODE_GCM)
+ * .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
* .build());
* // Key imported, obtain a reference to it.
* SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
@@ -232,7 +236,7 @@
}
/**
- * Gets the set of block modes (e.g., {@code CBC}, {@code CTR}) with which the key can be used
+ * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
* when encrypting/decrypting. Attempts to use the key with any other block modes will be
* rejected.
*
@@ -257,22 +261,32 @@
}
/**
- * Returns {@code true} if user authentication is required for this key to be used.
+ * Returns {@code true} if the key is authorized to be used only if the user has been
+ * authenticated.
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setUserAuthenticationRequired(boolean)
*/
public boolean isUserAuthenticationRequired() {
return mUserAuthenticationRequired;
}
/**
- * Gets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Gets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect only if user authentication is required
+ * (see {@link #isUserAuthenticationRequired()}).
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @return duration in seconds or {@code -1} if authentication is required for every use of the
* key.
*
* @see #isUserAuthenticationRequired()
+ * @see Builder#setUserAuthenticationValidityDurationSeconds(int)
*/
public int getUserAuthenticationValidityDurationSeconds() {
return mUserAuthenticationValidityDurationSeconds;
@@ -424,11 +438,11 @@
}
/**
- * Sets the set of block modes (e.g., {@code CBC}, {@code CTR}, {@code ECB}) with which the
- * key can be used when encrypting/decrypting. Attempts to use the key with any other block
- * modes will be rejected.
+ * Sets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be
+ * used when encrypting/decrypting. Attempts to use the key with any other block modes will
+ * be rejected.
*
- * <p>This must be specified for encryption/decryption keys.
+ * <p>This must be specified for symmetric encryption/decryption keys.
*
* <p>See {@link KeyProperties}.{@code BLOCK_MODE} constants.
*/
@@ -453,8 +467,8 @@
* <ul>
* <li>transformation which do not offer {@code IND-CPA}, such as symmetric ciphers using
* {@code ECB} mode or RSA encryption without padding, are prohibited;</li>
- * <li>in transformations which use an IV, such as symmetric ciphers in {@code CBC},
- * {@code CTR}, and {@code GCM} block modes, caller-provided IVs are rejected when
+ * <li>in transformations which use an IV, such as symmetric ciphers in {@code GCM},
+ * {@code CBC}, and {@code CTR} block modes, caller-provided IVs are rejected when
* encrypting, to ensure that only random IVs are used.</li>
*
* <p>Before disabling this requirement, consider the following approaches instead:
@@ -479,19 +493,38 @@
}
/**
- * Sets whether user authentication is required to use this key.
+ * Sets whether this key is authorized to be used only if the user has been authenticated.
*
- * <p>By default, the key can be used without user authentication.
+ * <p>By default, the key is authorized to be used regardless of whether the user has been
+ * authenticated.
*
- * <p>When user authentication is required, the user authorizes the use of the key by
- * authenticating to this Android device using a subset of their secure lock screen
- * credentials. Different authentication methods are used depending on whether the every
- * use of the key must be authenticated (as specified by
- * {@link #setUserAuthenticationValidityDurationSeconds(int)}).
+ * <p>When user authentication is required:
+ * <ul>
+ * <li>The key can only be import if secure lock screen is set up (see
+ * {@link KeyguardManager#isDeviceSecure()}). Additionally, if the key requires that user
+ * authentication takes place for every use of the key (see
+ * {@link #setUserAuthenticationValidityDurationSeconds(int)}), at least one fingerprint
+ * must be enrolled (see {@link FingerprintManager#hasEnrolledFingerprints()}).</li>
+ * <li>The use of the key must be authorized by the user by authenticating to this Android
+ * device using a subset of their secure lock screen credentials such as
+ * password/PIN/pattern or fingerprint.
* <a href="{@docRoot}training/articles/keystore.html#UserAuthentication">More
* information</a>.
+ * <li>The key will become <em>irreversibly invalidated</em> once the secure lock screen is
+ * disabled (reconfigured to None, Swipe or other mode which does not authenticate the user)
+ * or when the secure lock screen is forcibly reset (e.g., by a Device Administrator).
+ * Additionally, if the key requires that user authentication takes place for every use of
+ * the key, it is also irreversibly invalidated once a new fingerprint is enrolled or once\
+ * no more fingerprints are enrolled. Attempts to initialize cryptographic operations using
+ * such keys will throw {@link KeyPermanentlyInvalidatedException}.</li>
+ * </ul>
+ *
+ * <p>This authorization applies only to secret key and private key operations. Public key
+ * operations are not restricted.
*
* @see #setUserAuthenticationValidityDurationSeconds(int)
+ * @see KeyguardManager#isDeviceSecure()
+ * @see FingerprintManager#hasEnrolledFingerprints()
*/
@NonNull
public Builder setUserAuthenticationRequired(boolean required) {
@@ -500,15 +533,39 @@
}
/**
- * Sets the duration of time (seconds) for which this key can be used after the user is
- * successfully authenticated. This has effect only if user authentication is required.
+ * Sets the duration of time (seconds) for which this key is authorized to be used after the
+ * user is successfully authenticated. This has effect if the key requires user
+ * authentication for its use (see {@link #setUserAuthenticationRequired(boolean)}).
*
- * <p>By default, the user needs to authenticate for every use of the key.
+ * <p>By default, if user authentication is required, it must take place for every use of
+ * the key.
*
- * @param seconds duration in seconds or {@code -1} if the user needs to authenticate for
- * every use of the key.
+ * <p>Cryptographic operations involving keys which require user authentication to take
+ * place for every operation can only use fingerprint authentication. This is achieved by
+ * initializing a cryptographic operation ({@link Signature}, {@link Cipher}, {@link Mac})
+ * with the key, wrapping it into a {@link FingerprintManager.CryptoObject}, invoking
+ * {@code FingerprintManager.authenticate} with {@code CryptoObject}, and proceeding with
+ * the cryptographic operation only if the authentication flow succeeds.
+ *
+ * <p>Cryptographic operations involving keys which are authorized to be used for a duration
+ * of time after a successful user authentication event can only use secure lock screen
+ * authentication. These cryptographic operations will throw
+ * {@link UserNotAuthenticatedException} during initialization if the user needs to be
+ * authenticated to proceed. This situation can be resolved by the user unlocking the secure
+ * lock screen of the Android or by going through the confirm credential flow initiated by
+ * {@link KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence, CharSequence)}.
+ * Once resolved, initializing a new cryptographic operation using this key (or any other
+ * key which is authorized to be used for a fixed duration of time after user
+ * authentication) should succeed provided the user authentication flow completed
+ * successfully.
+ *
+ * @param seconds duration in seconds or {@code -1} if user authentication must take place
+ * for every use of the key.
*
* @see #setUserAuthenticationRequired(boolean)
+ * @see FingerprintManager
+ * @see FingerprintManager.CryptoObject
+ * @see KeyguardManager
*/
@NonNull
public Builder setUserAuthenticationValidityDurationSeconds(
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 3cbc405..974b62e 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -527,10 +527,11 @@
}
/**
- * @return a new {@link AudioRecord} instance initialized with all the parameters set
- * on this <code>Builder</code>
+ * @return a new {@link AudioRecord} instance successfully initialized with all
+ * the parameters set on this <code>Builder</code>.
* @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
- * were incompatible, or if they are not supported by the device.
+ * were incompatible, or if they are not supported by the device,
+ * or if the device was not available.
*/
public AudioRecord build() throws UnsupportedOperationException {
if (mFormat == null) {
@@ -564,7 +565,13 @@
mBufferSizeInBytes = mFormat.getChannelCount()
* mFormat.getBytesPerSample(mFormat.getEncoding());
}
- return new AudioRecord(mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
+ final AudioRecord record = new AudioRecord(
+ mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
+ if (record.getState() == STATE_UNINITIALIZED) {
+ // release is not necessary
+ throw new UnsupportedOperationException("Cannot create AudioRecord");
+ }
+ return record;
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException(e.getMessage());
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index f395cb3..62810c6 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -661,9 +661,10 @@
/**
* Builds an {@link AudioTrack} instance initialized with all the parameters set
* on this <code>Builder</code>.
- * @return a new {@link AudioTrack} instance.
+ * @return a new successfully initialized {@link AudioTrack} instance.
* @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
- * were incompatible, or if they are not supported by the device.
+ * were incompatible, or if they are not supported by the device,
+ * or if the device was not available.
*/
public @NonNull AudioTrack build() throws UnsupportedOperationException {
if (mAttributes == null) {
@@ -686,7 +687,13 @@
mBufferSizeInBytes = mFormat.getChannelCount()
* mFormat.getBytesPerSample(mFormat.getEncoding());
}
- return new AudioTrack(mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId);
+ final AudioTrack track = new AudioTrack(
+ mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId);
+ if (track.getState() == STATE_UNINITIALIZED) {
+ // release is not necessary
+ throw new UnsupportedOperationException("Cannot create AudioTrack");
+ }
+ return track;
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException(e.getMessage());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index f57575d..10c35af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -110,6 +110,8 @@
mInitialTouchX = x;
mInitialTouchY = y;
int expandedHeight = mPickedChild.getActualHeight();
+ mPanel.setPanelScrimMinFraction((float) expandedHeight
+ / mPanel.getMaxPanelHeight());
mPanel.startExpandMotion(x, y, true /* startTracking */, expandedHeight
+ mNotificationsTopPadding);
mHeadsUpManager.unpinAll();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 5ac436a..495f0fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1767,6 +1767,7 @@
mIsExpansionFromHeadsUp = false;
mNotificationStackScroller.setTrackingHeadsUp(false);
mExpandingFromHeadsUp = false;
+ setPanelScrimMinFraction(0.0f);
}
private void setListening(boolean listening) {
@@ -2317,7 +2318,7 @@
}
x = Math.min(rightMost, Math.max(leftMost, x));
setVerticalPanelTranslation(x -
- (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth()/2));
+ (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2));
}
private void resetVerticalPanelPosition() {
@@ -2334,4 +2335,8 @@
mNotificationStackScroller.setStackHeight(stackHeight);
updateKeyguardBottomAreaAlpha();
}
+
+ public void setPanelScrimMinFraction(float minFraction) {
+ mBar.panelScrimMinFractionChanged(minFraction);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 552a0b2..cf553ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -25,7 +25,7 @@
import java.util.ArrayList;
-public class PanelBar extends FrameLayout {
+public abstract class PanelBar extends FrameLayout {
public static final boolean DEBUG = false;
public static final String TAG = PanelBar.class.getSimpleName();
public static final void LOG(String fmt, Object... args) {
@@ -156,6 +156,8 @@
}
}
+ public abstract void panelScrimMinFractionChanged(float minFraction);
+
/**
* @param panel the panel which changed its expansion state
* @param frac the fraction from the expansion in [0, 1]
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index b7e675d..dfd280a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -40,6 +40,8 @@
PanelView mNotificationPanel;
private final PhoneStatusBarTransitions mBarTransitions;
private ScrimController mScrimController;
+ private float mMinFraction;
+ private float mPanelFraction;
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -180,8 +182,22 @@
}
@Override
+ public void panelScrimMinFractionChanged(float minFraction) {
+ if (mMinFraction != minFraction) {
+ mMinFraction = minFraction;
+ updateScrimFraction();
+ }
+ }
+
+ @Override
public void panelExpansionChanged(PanelView panel, float frac, boolean expanded) {
super.panelExpansionChanged(panel, frac, expanded);
- mScrimController.setPanelExpansion(frac);
+ mPanelFraction = frac;
+ updateScrimFraction();
+ }
+
+ private void updateScrimFraction() {
+ float scrimFraction = Math.max(mPanelFraction - mMinFraction / (1.0f - mMinFraction), 0);
+ mScrimController.setPanelExpansion(scrimFraction);
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 0b430ca0..47a230a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -180,8 +180,6 @@
public boolean showLocked(Bundle args, int flags,
IVoiceInteractionSessionShowCallback showCallback) {
- // For now we never allow screenshots.
- flags &= ~VoiceInteractionSession.SHOW_WITH_SCREENSHOT;
if (mBound) {
if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@@ -190,13 +188,15 @@
new UserHandle(mUser));
}
mShown = true;
+ boolean allDataEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0;
mShowArgs = args;
mShowFlags = flags;
mHaveAssistData = false;
if ((flags& VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
- && isStructureEnabled()) {
+ && allDataEnabled) {
try {
mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
mAssistReceiver);
@@ -212,7 +212,8 @@
mHaveScreenshot = false;
if ((flags& VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_SCREENSHOT, mCallingUid,
- mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED) {
+ mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
+ && allDataEnabled) {
try {
mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
} catch (RemoteException e) {
@@ -466,11 +467,6 @@
mService = null;
}
- private boolean isStructureEnabled() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0;
- }
-
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
pw.print(prefix); pw.print("mShown="); pw.println(mShown);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3f78497..0eb94b8 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -182,6 +182,34 @@
public static final String
KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ /**
+ * Override the platform's notion of a network operator being considered roaming.
+ * Value is string array of MCCMNCs to be considered roaming for 3GPP RATs.
+ */
+ public static final String
+ KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
+
+ /**
+ * Override the platform's notion of a network operator being considered not roaming.
+ * Value is string array of MCCMNCs to be considered not roaming for 3GPP RATs.
+ */
+ public static final String
+ KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
+
+ /**
+ * Override the platform's notion of a network operator being considered roaming.
+ * Value is string array of SIDs to be considered roaming for 3GPP2 RATs.
+ */
+ public static final String
+ KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
+
+ /**
+ * Override the platform's notion of a network operator being considered non roaming.
+ * Value is string array of SIDs to be considered not roaming for 3GPP2 RATs.
+ */
+ public static final String
+ KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
+
/**
* Flag specifying whether VoLTE should be available for carrier, independent of carrier
* provisioning. If false: hard disabled. If true: then depends on carrier provisioning,
@@ -358,6 +386,11 @@
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING, "");
+ sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null);
+
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL, true);
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 674777e..8443490 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -153,17 +153,17 @@
/**
* The outgoing call failed with an unknown cause.
*/
- public static final int OUTGOING_FAILURE = 43;
+ public static final int OUTGOING_FAILURE = 43;
/**
* The outgoing call was canceled by the {@link android.telecom.ConnectionService}.
*/
- public static final int OUTGOING_CANCELED = 44;
+ public static final int OUTGOING_CANCELED = 44;
/**
* The call, which was an IMS call, disconnected because it merged with another call.
*/
- public static final int IMS_MERGED_SUCCESSFULLY = 45;
+ public static final int IMS_MERGED_SUCCESSFULLY = 45;
/**
* Stk Call Control modified DIAL request to USSD request.
@@ -181,6 +181,12 @@
*/
public static final int DIAL_MODIFIED_TO_DIAL = 48;
+ /**
+ * The call was terminated because CDMA phone service and roaming have already been activated.
+ * {@hide}
+ */
+ public static final int CDMA_ALREADY_ACTIVATED = 49;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -189,14 +195,14 @@
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 49
+ // NextId: 50
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = DIAL_MODIFIED_TO_DIAL;
+ public static final int MAXIMUM_VALID_VALUE = CDMA_ALREADY_ACTIVATED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -302,6 +308,8 @@
return "OUTGOING_CANCELED";
case IMS_MERGED_SUCCESSFULLY:
return "IMS_MERGED_SUCCESSFULLY";
+ case CDMA_ALREADY_ACTIVATED:
+ return "CDMA_ALREADY_ACTIVATED";
default:
return "INVALID: " + cause;
}