diff options
17 files changed, 709 insertions, 133 deletions
diff --git a/api/current.txt b/api/current.txt index 418940918654..47d32077861a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5793,6 +5793,7 @@ package android.app.admin { method public boolean getCameraDisabled(android.content.ComponentName); method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException; method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName); + method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName); method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName); method public int getCurrentFailedPasswordAttempts(); method public java.lang.String getDeviceOwnerLockScreenInfo(); @@ -5857,6 +5858,7 @@ package android.app.admin { method public void setCameraDisabled(android.content.ComponentName, boolean); method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean); + method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean); method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); @@ -12784,6 +12786,7 @@ package android.graphics.drawable { method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); field public static final int PADDING_MODE_NEST = 0; // 0x0 field public static final int PADDING_MODE_STACK = 1; // 0x1 + field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000 } public class LevelListDrawable extends android.graphics.drawable.DrawableContainer { diff --git a/api/system-current.txt b/api/system-current.txt index a63a0731d7cf..dbbc04be2730 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5919,6 +5919,7 @@ package android.app.admin { method public boolean getCameraDisabled(android.content.ComponentName); method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException; method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName); + method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName); method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName); method public int getCurrentFailedPasswordAttempts(); method public deprecated java.lang.String getDeviceInitializerApp(); @@ -5992,6 +5993,7 @@ package android.app.admin { method public void setCameraDisabled(android.content.ComponentName, boolean); method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean); + method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean); method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); @@ -13139,6 +13141,7 @@ package android.graphics.drawable { method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); field public static final int PADDING_MODE_NEST = 0; // 0x0 field public static final int PADDING_MODE_STACK = 1; // 0x1 + field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000 } public class LevelListDrawable extends android.graphics.drawable.DrawableContainer { diff --git a/api/test-current.txt b/api/test-current.txt index f15ab581877b..6eba6bd7a2df 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5795,6 +5795,7 @@ package android.app.admin { method public boolean getCameraDisabled(android.content.ComponentName); method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException; method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName); + method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName); method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName); method public int getCurrentFailedPasswordAttempts(); method public java.lang.String getDeviceOwnerLockScreenInfo(); @@ -5859,6 +5860,7 @@ package android.app.admin { method public void setCameraDisabled(android.content.ComponentName, boolean); method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean); + method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean); method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); @@ -12792,6 +12794,7 @@ package android.graphics.drawable { method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); field public static final int PADDING_MODE_NEST = 0; // 0x0 field public static final int PADDING_MODE_STACK = 1; // 0x1 + field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000 } public class LevelListDrawable extends android.graphics.drawable.DrawableContainer { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 08e9b1e897af..4de3ceb4792e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3540,6 +3540,66 @@ public class DevicePolicyManager { } /** + * Called by a profile owner of a managed profile to set whether contacts search from + * the managed profile will be shown in the parent profile, for incoming calls. + * + * <p>The calling device admin must be a profile owner. If it is not, a + * security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param disabled If true contacts search in the managed profile is not displayed. + */ + public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin, + boolean disabled) { + if (mService != null) { + try { + mService.setCrossProfileContactsSearchDisabled(admin, disabled); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + } + + /** + * Called by a profile owner of a managed profile to determine whether or not contacts search + * has been disabled. + * + * <p>The calling device admin must be a profile owner. If it is not, a + * security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + */ + public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) { + if (mService != null) { + try { + return mService.getCrossProfileContactsSearchDisabled(admin); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + return false; + } + + + /** + * Determine whether or not contacts search has been disabled. + * + * @param userHandle The user for whom to check the contacts search permission + * @hide + */ + public boolean getCrossProfileContactsSearchDisabled(@NonNull UserHandle userHandle) { + if (mService != null) { + try { + return mService + .getCrossProfileContactsSearchDisabledForUser(userHandle.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + return false; + } + + /** * Start Quick Contact on the managed profile for the user, if the policy allows. * @hide */ diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 754cb432bf7c..d3c32c51798a 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -202,6 +202,9 @@ interface IDevicePolicyManager { void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled); boolean getCrossProfileCallerIdDisabled(in ComponentName who); boolean getCrossProfileCallerIdDisabledForUser(int userId); + void setCrossProfileContactsSearchDisabled(in ComponentName who, boolean disabled); + boolean getCrossProfileContactsSearchDisabled(in ComponentName who); + boolean getCrossProfileContactsSearchDisabledForUser(int userId); void startManagedQuickContact(String lookupKey, long contactId, long directoryId, in Intent originalIntent); void setBluetoothContactSharingDisabled(in ComponentName who, boolean disabled); diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index c79e18449e39..09cf7049c04a 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -271,6 +271,10 @@ public class Spinner extends AbsSpinner implements OnClickListener { attrs, R.styleable.Spinner, defStyleAttr, defStyleRes); mDropDownWidth = pa.getLayoutDimension(R.styleable.Spinner_dropDownWidth, ViewGroup.LayoutParams.WRAP_CONTENT); + if (pa.hasValueOrEmpty(R.styleable.Spinner_dropDownSelector)) { + popup.setListSelector(pa.getDrawable( + R.styleable.Spinner_dropDownSelector)); + } popup.setBackgroundDrawable(pa.getDrawable(R.styleable.Spinner_popupBackground)); popup.setPromptText(a.getString(R.styleable.Spinner_prompt)); pa.recycle(); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index f159a4d71f20..b4c4ef506f46 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -2677,20 +2677,16 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { invalidatePanelMenu(FEATURE_ACTION_BAR); } } else { - mTitleView = (TextView)findViewById(R.id.title); + mTitleView = (TextView) findViewById(R.id.title); if (mTitleView != null) { - mTitleView.setLayoutDirection(mDecor.getLayoutDirection()); if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) { - View titleContainer = findViewById( - R.id.title_container); + final View titleContainer = findViewById(R.id.title_container); if (titleContainer != null) { titleContainer.setVisibility(View.GONE); } else { mTitleView.setVisibility(View.GONE); } - if (mContentParent instanceof FrameLayout) { - ((FrameLayout)mContentParent).setForeground(null); - } + mContentParent.setForeground(null); } else { mTitleView.setText(mTitle); } diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 651b45334ee0..e2150c02c0e6 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -82,8 +82,13 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { */ public static final int PADDING_MODE_STACK = 1; - /** Value used for undefined start and end insets. */ - private static final int UNDEFINED_INSET = Integer.MIN_VALUE; + /** + * Value used for undefined start and end insets. + * + * @see #getLayerInsetStart(int) + * @see #getLayerInsetEnd(int) + */ + public static final int UNDEFINED_INSET = Integer.MIN_VALUE; LayerState mLayerState; @@ -867,7 +872,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { /** * @param index the index of the layer - * @return number of pixels to inset from the start bound + * @return the number of pixels to inset from the start bound, or + * {@link #UNDEFINED_INSET} if not specified * @attr ref android.R.styleable#LayerDrawableItem_start */ public int getLayerInsetStart(int index) { @@ -877,7 +883,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { /** * @param index the index of the layer to adjust - * @param e number of pixels to inset from the end bound + * @param e number of pixels to inset from the end bound, or + * {@link #UNDEFINED_INSET} if not specified * @attr ref android.R.styleable#LayerDrawableItem_end */ public void setLayerInsetEnd(int index, int e) { @@ -977,34 +984,33 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { computeStackedPadding(padding); } + final int paddingT = layerState.mPaddingTop; + final int paddingB = layerState.mPaddingBottom; + + // Resolve padding for RTL. Relative padding overrides absolute + // padding. + final boolean isLayoutRtl = getLayoutDirection() == LayoutDirection.RTL; + final int paddingRtlL = isLayoutRtl ? layerState.mPaddingEnd : layerState.mPaddingStart; + final int paddingRtlR = isLayoutRtl ? layerState.mPaddingStart : layerState.mPaddingEnd; + final int paddingL = paddingRtlL >= 0 ? paddingRtlL : layerState.mPaddingLeft; + final int paddingR = paddingRtlR >= 0 ? paddingRtlR : layerState.mPaddingRight; + // If padding was explicitly specified (e.g. not -1) then override the // computed padding in that dimension. - if (layerState.mPaddingTop >= 0) { - padding.top = layerState.mPaddingTop; - } - - if (layerState.mPaddingBottom >= 0) { - padding.bottom = layerState.mPaddingBottom; + if (paddingL >= 0) { + padding.left = paddingL; } - final int paddingRtlLeft; - final int paddingRtlRight; - if (getLayoutDirection() == LayoutDirection.RTL) { - paddingRtlLeft = layerState.mPaddingEnd; - paddingRtlRight = layerState.mPaddingStart; - } else { - paddingRtlLeft = layerState.mPaddingStart; - paddingRtlRight = layerState.mPaddingEnd; + if (paddingT >= 0) { + padding.top = paddingT; } - final int paddingLeft = paddingRtlLeft >= 0 ? paddingRtlLeft : layerState.mPaddingLeft; - if (paddingLeft >= 0) { - padding.left = paddingLeft; + if (paddingR >= 0) { + padding.right = paddingR; } - final int paddingRight = paddingRtlRight >= 0 ? paddingRtlRight : layerState.mPaddingRight; - if (paddingRight >= 0) { - padding.right = paddingRight; + if (paddingB >= 0) { + padding.bottom = paddingB; } return padding.left != 0 || padding.top != 0 || padding.right != 0 || padding.bottom != 0; @@ -1471,58 +1477,59 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } private void updateLayerBounds(Rect bounds) { - int padL = 0; - int padT = 0; - int padR = 0; - int padB = 0; + int paddingL = 0; + int paddingT = 0; + int paddingR = 0; + int paddingB = 0; final Rect outRect = mTmpOutRect; final int layoutDirection = getLayoutDirection(); - final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST; + final boolean isLayoutRtl = layoutDirection == LayoutDirection.RTL; + final boolean isPaddingNested = mLayerState.mPaddingMode == PADDING_MODE_NEST; final ChildDrawable[] array = mLayerState.mChildren; - final int N = mLayerState.mNum; - for (int i = 0; i < N; i++) { + + for (int i = 0, count = mLayerState.mNum; i < count; i++) { final ChildDrawable r = array[i]; final Drawable d = r.mDrawable; if (d == null) { continue; } - final Rect container = mTmpContainer; - container.set(d.getBounds()); + final int insetT = r.mInsetT; + final int insetB = r.mInsetB; - // 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; - 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; - } + // Resolve insets for RTL. Relative insets override absolute + // insets. + final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS; + final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE; + final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL; + final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR; // Establish containing region based on aggregate padding and // requested insets for the current layer. - container.set(bounds.left + insetL + padL, bounds.top + r.mInsetT + padT, - bounds.right - insetR - padR, bounds.bottom - r.mInsetB - padB); - - // Apply resolved gravity to drawable based on resolved size. - final int gravity = resolveGravity(r.mGravity, r.mWidth, r.mHeight, - d.getIntrinsicWidth(), d.getIntrinsicHeight()); - final int w = r.mWidth < 0 ? d.getIntrinsicWidth() : r.mWidth; - final int h = r.mHeight < 0 ? d.getIntrinsicHeight() : r.mHeight; - Gravity.apply(gravity, w, h, container, outRect, layoutDirection); + final Rect container = mTmpContainer; + container.set(bounds.left + insetL + paddingL, bounds.top + insetT + paddingT, + bounds.right - insetR - paddingR, bounds.bottom - insetB - paddingB); + + // Compute a reasonable default gravity based on the intrinsic and + // explicit dimensions, if specified. + final int intrinsicW = d.getIntrinsicWidth(); + final int intrinsicH = d.getIntrinsicHeight(); + final int layerW = r.mWidth; + final int layerH = r.mHeight; + final int gravity = resolveGravity(r.mGravity, layerW, layerH, intrinsicW, intrinsicH); + + // Explicit dimensions override intrinsic dimensions. + final int resolvedW = layerW < 0 ? intrinsicW : layerW; + final int resolvedH = layerH < 0 ? intrinsicH : layerH; + Gravity.apply(gravity, resolvedW, resolvedH, container, outRect, layoutDirection); d.setBounds(outRect); - if (nest) { - padL += mPaddingL[i]; - padR += mPaddingR[i]; - padT += mPaddingT[i]; - padB += mPaddingB[i]; + if (isPaddingNested) { + paddingL += mPaddingL[i]; + paddingR += mPaddingR[i]; + paddingT += mPaddingT[i]; + paddingB += mPaddingB[i]; } } } @@ -1578,6 +1585,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { int padR = 0; final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST; + final boolean isLayoutRtl = getLayoutDirection() == LayoutDirection.RTL; final ChildDrawable[] array = mLayerState.mChildren; final int N = mLayerState.mNum; for (int i = 0; i < N; i++) { @@ -1591,15 +1599,10 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { // 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 insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS; + final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE; + final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL; + final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR; // Don't apply padding and insets for children that don't have // an intrinsic dimension. @@ -1659,8 +1662,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { if (r.mDrawable != null) { final Rect rect = mTmpRect; r.mDrawable.getPadding(rect); - if (rect.left != mPaddingL[i] || rect.top != mPaddingT[i] || - rect.right != mPaddingR[i] || rect.bottom != mPaddingB[i]) { + if (rect.left != mPaddingL[i] || rect.top != mPaddingT[i] + || rect.right != mPaddingR[i] || rect.bottom != mPaddingB[i]) { mPaddingL[i] = rect.left; mPaddingT[i] = rect.top; mPaddingR[i] = rect.right; diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 478fd992c3bd..f1f84375c36b 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -2175,8 +2175,6 @@ final public class MediaCodec { int offset, int size, long presentationTimeUs, int flags) throws CryptoException; - // The following mode constants MUST stay in sync with their equivalents - // in media/hardware/CryptoAPI.h ! public static final int CRYPTO_MODE_UNENCRYPTED = 0; public static final int CRYPTO_MODE_AES_CTR = 1; public static final int CRYPTO_MODE_AES_CBC = 2; diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 49b579ce438d..2004a3aef2b8 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -85,6 +85,13 @@ static struct { jmethodID setNativeObjectLocked; } gPersistentSurfaceClassInfo; +static struct { + jint Unencrypted; + jint AesCtr; + jint AesCbc; +} gCryptoModes; + + struct fields_t { jfieldID context; jmethodID postEventFromNativeID; @@ -94,6 +101,9 @@ struct fields_t { jfieldID cryptoInfoKeyID; jfieldID cryptoInfoIVID; jfieldID cryptoInfoModeID; + jfieldID cryptoInfoPatternID; + jfieldID patternEncryptBlocksID; + jfieldID patternSkipBlocksID; }; static fields_t gFields; @@ -325,11 +335,12 @@ status_t JMediaCodec::queueSecureInputBuffer( const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, + const CryptoPlugin::Pattern &pattern, int64_t presentationTimeUs, uint32_t flags, AString *errorDetailMsg) { return mCodec->queueSecureInputBuffer( - index, offset, subSamples, numSubSamples, key, iv, mode, + index, offset, subSamples, numSubSamples, key, iv, mode, pattern, presentationTimeUs, flags, errorDetailMsg); } @@ -1275,7 +1286,26 @@ static void android_media_MediaCodec_queueSecureInputBuffer( jbyteArray ivObj = (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID); - jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID); + jint jmode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID); + enum CryptoPlugin::Mode mode; + if (jmode == gCryptoModes.Unencrypted) { + mode = CryptoPlugin::kMode_Unencrypted; + } else if (jmode == gCryptoModes.AesCtr) { + mode = CryptoPlugin::kMode_AES_CTR; + } else if (jmode == gCryptoModes.AesCbc) { + mode = CryptoPlugin::kMode_AES_CBC; + } else { + throwExceptionAsNecessary(env, INVALID_OPERATION); + return; + } + + jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID); + + CryptoPlugin::Pattern pattern; + if (patternObj != NULL) { + pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID); + pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID); + } status_t err = OK; @@ -1360,7 +1390,8 @@ static void android_media_MediaCodec_queueSecureInputBuffer( index, offset, subSamples, numSubSamples, (const uint8_t *)key, (const uint8_t *)iv, - (CryptoPlugin::Mode)mode, + mode, + pattern, timestampUs, flags, &errorDetailMsg); @@ -1658,6 +1689,22 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) { CHECK(gFields.postEventFromNativeID != NULL); + jfieldID field; + field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_UNENCRYPTED", "I"); + CHECK(field != NULL); + gCryptoModes.Unencrypted = + env->GetStaticIntField(clazz.get(), field); + + field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CTR", "I"); + CHECK(field != NULL); + gCryptoModes.AesCtr = + env->GetStaticIntField(clazz.get(), field); + + field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CBC", "I"); + CHECK(field != NULL); + gCryptoModes.AesCbc = + env->GetStaticIntField(clazz.get(), field); + clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo")); CHECK(clazz.get() != NULL); @@ -1682,10 +1729,22 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) { gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I"); CHECK(gFields.cryptoInfoModeID != NULL); + gFields.cryptoInfoPatternID = env->GetFieldID(clazz.get(), "pattern", + "Landroid/media/MediaCodec$CryptoInfo$Pattern;"); + CHECK(gFields.cryptoInfoPatternID != NULL); + + clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo$Pattern")); + CHECK(clazz.get() != NULL); + + gFields.patternEncryptBlocksID = env->GetFieldID(clazz.get(), "mEncryptBlocks", "I"); + CHECK(gFields.patternEncryptBlocksID != NULL); + + gFields.patternSkipBlocksID = env->GetFieldID(clazz.get(), "mSkipBlocks", "I"); + CHECK(gFields.patternSkipBlocksID != NULL); + clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException")); CHECK(clazz.get() != NULL); - jfieldID field; field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I"); CHECK(field != NULL); gCryptoErrorCodes.cryptoErrorNoKey = diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 6650cf9254e1..c0c47ef2aeda 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -81,6 +81,7 @@ struct JMediaCodec : public AHandler { const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, + const CryptoPlugin::Pattern &pattern, int64_t presentationTimeUs, uint32_t flags, AString *errorDetailMsg); diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index ac19cf50d62a..6dfa9ad2d26e 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -684,6 +684,8 @@ <string name="select_webview_provider_title">WebView implementation</string> <!-- Developer settings: select WebView provider dialog title --> <string name="select_webview_provider_dialog_title">Set WebView implementation</string> + <!-- Developer settings: confirmation dialog text for the WebView provider selection dialog --> + <string name="select_webview_provider_confirmation_text">The chosen WebView implementation is disabled, and must be enabled to be used, do you wish to enable it?</string> <!-- Developer settings screen, convert userdata to file encryption option name --> <string name="convert_to_file_encryption">Convert to file encryption</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java new file mode 100644 index 000000000000..f1beb103d6c4 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java @@ -0,0 +1,371 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.settingslib.users; + +import android.app.AppGlobals; +import android.appwidget.AppWidgetManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.os.UserManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class AppRestrictionsHelper { + private static final boolean DEBUG = false; + private static final String TAG = "AppRestrictionsHelper"; + + private final Context mContext; + private final PackageManager mPackageManager; + private final IPackageManager mIPm; + private final UserManager mUserManager; + private final UserHandle mUser; + private final boolean mRestrictedProfile; + + HashMap<String,Boolean> mSelectedPackages = new HashMap<>(); + private List<SelectableAppInfo> mVisibleApps; + + public AppRestrictionsHelper(Context context, UserHandle user) { + mContext = context; + mPackageManager = context.getPackageManager(); + mIPm = AppGlobals.getPackageManager(); + mUser = user; + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mRestrictedProfile = mUserManager.getUserInfo(mUser.getIdentifier()).isRestricted(); + } + + public void setPackageSelected(String packageName, boolean selected) { + mSelectedPackages.put(packageName, selected); + } + + public boolean isPackageSelected(String packageName) { + return mSelectedPackages.get(packageName); + } + + public List<SelectableAppInfo> getVisibleApps() { + return mVisibleApps; + } + + public void applyUserAppsStates(OnDisableUiForPackageListener listener) { + final int userId = mUser.getIdentifier(); + if (!mUserManager.getUserInfo(userId).isRestricted() && userId != UserHandle.myUserId()) { + Log.e(TAG, "Cannot apply application restrictions on another user!"); + return; + } + for (Map.Entry<String,Boolean> entry : mSelectedPackages.entrySet()) { + String packageName = entry.getKey(); + boolean enabled = entry.getValue(); + applyUserAppState(packageName, enabled, listener); + } + } + + public void applyUserAppState(String packageName, boolean enabled, + OnDisableUiForPackageListener listener) { + final int userId = mUser.getIdentifier(); + if (enabled) { + // Enable selected apps + try { + ApplicationInfo info = mIPm.getApplicationInfo(packageName, + PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); + if (info == null || !info.enabled + || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { + mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier()); + if (DEBUG) { + Log.d(TAG, "Installing " + packageName); + } + } + if (info != null && (info.privateFlags&ApplicationInfo.PRIVATE_FLAG_HIDDEN) != 0 + && (info.flags&ApplicationInfo.FLAG_INSTALLED) != 0) { + listener.onDisableUiForPackage(packageName); + mIPm.setApplicationHiddenSettingAsUser(packageName, false, userId); + if (DEBUG) { + Log.d(TAG, "Unhiding " + packageName); + } + } + } catch (RemoteException re) { + // Ignore + } + } else { + // Blacklist all other apps, system or downloaded + try { + ApplicationInfo info = mIPm.getApplicationInfo(packageName, 0, userId); + if (info != null) { + if (mRestrictedProfile) { + mIPm.deletePackageAsUser(packageName, null, mUser.getIdentifier(), + PackageManager.DELETE_SYSTEM_APP); + if (DEBUG) { + Log.d(TAG, "Uninstalling " + packageName); + } + } else { + listener.onDisableUiForPackage(packageName); + mIPm.setApplicationHiddenSettingAsUser(packageName, true, userId); + if (DEBUG) { + Log.d(TAG, "Hiding " + packageName); + } + } + } + } catch (RemoteException re) { + // Ignore + } + } + } + + public void fetchAndMergeApps() { + mVisibleApps = new ArrayList<>(); + final PackageManager pm = mPackageManager; + final IPackageManager ipm = mIPm; + + final HashSet<String> excludePackages = new HashSet<>(); + addSystemImes(excludePackages); + + // Add launchers + Intent launcherIntent = new Intent(Intent.ACTION_MAIN); + launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER); + addSystemApps(mVisibleApps, launcherIntent, excludePackages); + + // Add widgets + Intent widgetIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + addSystemApps(mVisibleApps, widgetIntent, excludePackages); + + List<ApplicationInfo> installedApps = pm.getInstalledApplications( + PackageManager.MATCH_UNINSTALLED_PACKAGES); + for (ApplicationInfo app : installedApps) { + // If it's not installed, skip + if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue; + + if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 + && (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) { + // Downloaded app + SelectableAppInfo info = new SelectableAppInfo(); + info.packageName = app.packageName; + info.appName = app.loadLabel(pm); + info.activityName = info.appName; + info.icon = app.loadIcon(pm); + mVisibleApps.add(info); + } else { + try { + PackageInfo pi = pm.getPackageInfo(app.packageName, 0); + // If it's a system app that requires an account and doesn't see restricted + // accounts, mark for removal. It might get shown in the UI if it has an icon + // but will still be marked as false and immutable. + if (mRestrictedProfile + && pi.requiredAccountType != null && pi.restrictedAccountType == null) { + mSelectedPackages.put(app.packageName, false); + } + } catch (PackageManager.NameNotFoundException re) { + // Skip + } + } + } + + // Get the list of apps already installed for the user + List<ApplicationInfo> userApps = null; + try { + ParceledListSlice<ApplicationInfo> listSlice = ipm.getInstalledApplications( + PackageManager.MATCH_UNINSTALLED_PACKAGES, mUser.getIdentifier()); + if (listSlice != null) { + userApps = listSlice.getList(); + } + } catch (RemoteException re) { + // Ignore + } + + if (userApps != null) { + for (ApplicationInfo app : userApps) { + if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue; + + if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 + && (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) { + // Downloaded app + SelectableAppInfo info = new SelectableAppInfo(); + info.packageName = app.packageName; + info.appName = app.loadLabel(pm); + info.activityName = info.appName; + info.icon = app.loadIcon(pm); + mVisibleApps.add(info); + } + } + } + + // Sort the list of visible apps + Collections.sort(mVisibleApps, new AppLabelComparator()); + + // Remove dupes + Set<String> dedupPackageSet = new HashSet<String>(); + for (int i = mVisibleApps.size() - 1; i >= 0; i--) { + SelectableAppInfo info = mVisibleApps.get(i); + if (DEBUG) Log.i(TAG, info.toString()); + String both = info.packageName + "+" + info.activityName; + if (!TextUtils.isEmpty(info.packageName) + && !TextUtils.isEmpty(info.activityName) + && dedupPackageSet.contains(both)) { + mVisibleApps.remove(i); + } else { + dedupPackageSet.add(both); + } + } + + // Establish master/slave relationship for entries that share a package name + HashMap<String,SelectableAppInfo> packageMap = new HashMap<String,SelectableAppInfo>(); + for (SelectableAppInfo info : mVisibleApps) { + if (packageMap.containsKey(info.packageName)) { + info.masterEntry = packageMap.get(info.packageName); + } else { + packageMap.put(info.packageName, info); + } + } + } + + /** + * Find all pre-installed input methods that are marked as default + * and add them to an exclusion list so that they aren't + * presented to the user for toggling. + * Don't add non-default ones, as they may include other stuff that we + * don't need to auto-include. + * @param excludePackages the set of package names to append to + */ + private void addSystemImes(Set<String> excludePackages) { + InputMethodManager imm = (InputMethodManager) + mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + List<InputMethodInfo> imis = imm.getInputMethodList(); + for (InputMethodInfo imi : imis) { + try { + if (imi.isDefault(mContext) && isSystemPackage(imi.getPackageName())) { + excludePackages.add(imi.getPackageName()); + } + } catch (Resources.NotFoundException rnfe) { + // Not default + } + } + } + + /** + * Add system apps that match an intent to the list, excluding any packages in the exclude list. + * @param visibleApps list of apps to append the new list to + * @param intent the intent to match + * @param excludePackages the set of package names to be excluded, since they're required + */ + private void addSystemApps(List<SelectableAppInfo> visibleApps, Intent intent, + Set<String> excludePackages) { + final PackageManager pm = mPackageManager; + List<ResolveInfo> launchableApps = pm.queryIntentActivities(intent, + PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_UNINSTALLED_PACKAGES); + for (ResolveInfo app : launchableApps) { + if (app.activityInfo != null && app.activityInfo.applicationInfo != null) { + final String packageName = app.activityInfo.packageName; + int flags = app.activityInfo.applicationInfo.flags; + if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0 + || (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { + // System app + // Skip excluded packages + if (excludePackages.contains(packageName)) continue; + int enabled = pm.getApplicationEnabledSetting(packageName); + if (enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED + || enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { + // Check if the app is already enabled for the target user + ApplicationInfo targetUserAppInfo = getAppInfoForUser(packageName, + 0, mUser); + if (targetUserAppInfo == null + || (targetUserAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { + continue; + } + } + SelectableAppInfo info = new SelectableAppInfo(); + info.packageName = app.activityInfo.packageName; + info.appName = app.activityInfo.applicationInfo.loadLabel(pm); + info.icon = app.activityInfo.loadIcon(pm); + info.activityName = app.activityInfo.loadLabel(pm); + if (info.activityName == null) info.activityName = info.appName; + + visibleApps.add(info); + } + } + } + } + + private boolean isSystemPackage(String packageName) { + try { + final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); + if (pi.applicationInfo == null) return false; + final int flags = pi.applicationInfo.flags; + if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0 + || (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { + return true; + } + } catch (PackageManager.NameNotFoundException nnfe) { + // Missing package? + } + return false; + } + + private ApplicationInfo getAppInfoForUser(String packageName, int flags, UserHandle user) { + try { + return mIPm.getApplicationInfo(packageName, flags, user.getIdentifier()); + } catch (RemoteException re) { + return null; + } + } + + public interface OnDisableUiForPackageListener { + void onDisableUiForPackage(String packageName); + } + + public static class SelectableAppInfo { + public String packageName; + public CharSequence appName; + public CharSequence activityName; + public Drawable icon; + public SelectableAppInfo masterEntry; + + @Override + public String toString() { + return packageName + ": appName=" + appName + "; activityName=" + activityName + + "; icon=" + icon + "; masterEntry=" + masterEntry; + } + } + + private static class AppLabelComparator implements Comparator<SelectableAppInfo> { + + @Override + public int compare(SelectableAppInfo lhs, SelectableAppInfo rhs) { + String lhsLabel = lhs.activityName.toString(); + String rhsLabel = rhs.activityName.toString(); + return lhsLabel.toLowerCase().compareTo(rhsLabel.toLowerCase()); + } + } +} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4f75810678a5..b27b92d50d0f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -18330,9 +18330,12 @@ public final class ActivityManagerService extends ActivityManagerNative * dialog / global actions also might want different behaviors. */ private static final boolean shouldShowDialogs(Configuration config) { - return !(config.keyboard == Configuration.KEYBOARD_NOKEYS - && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH - && config.navigation == Configuration.NAVIGATION_NONAV); + final boolean inputMethodExists = !(config.keyboard == Configuration.KEYBOARD_NOKEYS + && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH + && config.navigation == Configuration.NAVIGATION_NONAV); + final boolean uiIsNotCarType = !((config.uiMode & Configuration.UI_MODE_TYPE_MASK) + == Configuration.UI_MODE_TYPE_CAR); + return inputMethodExists && uiIsNotCarType; } @Override diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index dd58b3c4443e..380763abf6e3 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -388,6 +388,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features"; private static final String TAG_DISABLE_CAMERA = "disable-camera"; private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id"; + private static final String TAG_DISABLE_CONTACTS_SEARCH = "disable-contacts-search"; private static final String TAG_DISABLE_BLUETOOTH_CONTACT_SHARING = "disable-bt-contacts-sharing"; private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture"; @@ -476,6 +477,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean encryptionRequested = false; boolean disableCamera = false; boolean disableCallerId = false; + boolean disableContactsSearch = false; boolean disableBluetoothContactSharing = true; boolean disableScreenCapture = false; // Can only be set by a device/profile owner. boolean requireAutoTime = false; // Can only be set by a device owner. @@ -638,6 +640,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, ATTR_VALUE, Boolean.toString(disableCallerId)); out.endTag(null, TAG_DISABLE_CALLER_ID); } + if (disableContactsSearch) { + out.startTag(null, TAG_DISABLE_CONTACTS_SEARCH); + out.attribute(null, ATTR_VALUE, Boolean.toString(disableContactsSearch)); + out.endTag(null, TAG_DISABLE_CONTACTS_SEARCH); + } if (disableBluetoothContactSharing) { out.startTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING); out.attribute(null, ATTR_VALUE, @@ -809,6 +816,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if (TAG_DISABLE_CALLER_ID.equals(tag)) { disableCallerId = Boolean.parseBoolean( parser.getAttributeValue(null, ATTR_VALUE)); + } else if (TAG_DISABLE_CONTACTS_SEARCH.equals(tag)) { + disableContactsSearch = Boolean.parseBoolean( + parser.getAttributeValue(null, ATTR_VALUE)); } else if (TAG_DISABLE_BLUETOOTH_CONTACT_SHARING.equals(tag)) { disableBluetoothContactSharing = Boolean.parseBoolean(parser .getAttributeValue(null, ATTR_VALUE)); @@ -1034,6 +1044,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.println(disableCamera); pw.print(prefix); pw.print("disableCallerId="); pw.println(disableCallerId); + pw.print(prefix); pw.print("disableContactsSearch="); + pw.println(disableContactsSearch); pw.print(prefix); pw.print("disableBluetoothContactSharing="); pw.println(disableBluetoothContactSharing); pw.print(prefix); pw.print("disableScreenCapture="); @@ -1808,7 +1820,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return null; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); Intent resolveIntent = new Intent(); resolveIntent.setComponent(adminName); List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceiversAsUser( @@ -2411,7 +2423,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Bundle onEnableData) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.MANAGE_DEVICE_ADMINS, null); - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); DevicePolicyData policy = getUserData(userHandle); DeviceAdminInfo info = findAdmin(adminReceiver, userHandle, @@ -2457,7 +2469,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return false; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null; } @@ -2468,7 +2480,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return false; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { DevicePolicyData policyData = getUserData(userHandle); return policyData.mRemovingAdmins.contains(adminReceiver); @@ -2480,7 +2492,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return false; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (administrator == null) { @@ -2497,7 +2509,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return Collections.EMPTY_LIST; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { DevicePolicyData policy = getUserData(userHandle); final int N = policy.mAdminList.size(); @@ -2517,7 +2529,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return false; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { DevicePolicyData policy = getUserData(userHandle); final int N = policy.mAdminList.size(); @@ -2535,7 +2547,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (admin == null) { @@ -2594,7 +2606,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; @@ -2664,7 +2676,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -2711,7 +2723,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -2771,7 +2783,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0L; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { long timeout = 0L; @@ -2898,7 +2910,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0L; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { return getPasswordExpirationLocked(who, userHandle); } @@ -2926,7 +2938,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -2970,7 +2982,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -3017,7 +3029,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -3067,7 +3079,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -3117,7 +3129,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -3167,7 +3179,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int length = 0; @@ -3200,7 +3212,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return true; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { int id = getCredentialOwner(userHandle); @@ -3272,7 +3284,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { ActiveAdmin admin = (who != null) ? getActiveAdminUncheckedLocked(who, userHandle) : getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle); @@ -3285,7 +3297,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return UserHandle.USER_NULL; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { ActiveAdmin admin = getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle); return admin != null ? admin.getUserHandle().getIdentifier() : UserHandle.USER_NULL; @@ -3584,7 +3596,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { long time = 0; @@ -3906,7 +3918,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } final int userHandle = mInjector.userHandleGetCallingUserId(); - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. @@ -3985,7 +3997,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); @@ -4014,7 +4026,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); // Managed Profile password can only be changed when per user encryption is present. if (!LockPatternUtils.isSeparateWorkChallengeEnabled()) { enforceNotManagedProfile(userHandle, "set the active password"); @@ -4083,7 +4095,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void reportFailedPasswordAttempt(int userHandle) { - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); enforceNotManagedProfile(userHandle, "report failed password attempt"); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); @@ -4125,7 +4137,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void reportSuccessfulPasswordAttempt(int userHandle) { - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); @@ -4209,7 +4221,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return null; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized(this) { DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM); // Scan through active admins and find if anyone has already @@ -4346,7 +4358,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return false; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { // Check for permissions if a particular caller is specified if (who != null) { @@ -4376,7 +4388,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { // Ok to return current status. } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); return getEncryptionStatus(); } @@ -4624,7 +4636,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return 0; } - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); long ident = mInjector.binderClearCallingIdentity(); try { synchronized (this) { @@ -5185,17 +5197,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void enforceCrossUserPermission(int userHandle) { + private void enforceFullCrossUsersPermission(int userHandle) { + enforceSystemUserOrPermission(userHandle, + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); + } + + private void enforceCrossUsersPermission(int userHandle) { + enforceSystemUserOrPermission(userHandle, + android.Manifest.permission.INTERACT_ACROSS_USERS); + } + + private void enforceSystemUserOrPermission(int userHandle, String permission) { if (userHandle < 0) { throw new IllegalArgumentException("Invalid userId " + userHandle); } final int callingUid = mInjector.binderGetCallingUid(); - if (userHandle == UserHandle.getUserId(callingUid)) return; + if (userHandle == UserHandle.getUserId(callingUid)) { + return; + } if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) || callingUid == Process.ROOT_UID)) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have" - + " INTERACT_ACROSS_USERS_FULL permission"); + mContext.enforceCallingOrSelfPermission(permission, + "Must be system or have " + permission + " permission"); } } @@ -5405,7 +5428,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return null; } Preconditions.checkNotNull(agent, "agent null"); - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { final String componentName = agent.flattenToString(); @@ -6068,7 +6091,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public Bundle getUserRestrictions(ComponentName who, int userHandle) { Preconditions.checkNotNull(who, "ComponentName is null"); - enforceCrossUserPermission(userHandle); + enforceFullCrossUsersPermission(userHandle); synchronized (this) { ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(who, userHandle); if (activeAdmin == null) { @@ -6260,7 +6283,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public String[] getAccountTypesWithManagementDisabledAsUser(int userId) { - enforceCrossUserPermission(userId); + enforceFullCrossUsersPermission(userId); if (!mHasFeature) { return null; } @@ -6332,7 +6355,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); if (admin.disableCallerId != disabled) { admin.disableCallerId = disabled; - saveSettingsLocked(UserHandle.getCallingUserId()); + saveSettingsLocked(mInjector.userHandleGetCallingUserId()); } } } @@ -6352,8 +6375,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public boolean getCrossProfileCallerIdDisabledForUser(int userId) { - // TODO: Should there be a check to make sure this relationship is within a profile group? - //enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system"); + enforceCrossUsersPermission(userId); synchronized (this) { ActiveAdmin admin = getProfileOwnerAdminLocked(userId); return (admin != null) ? admin.disableCallerId : false; @@ -6361,6 +6383,44 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override + public void setCrossProfileContactsSearchDisabled(ComponentName who, boolean disabled) { + if (!mHasFeature) { + return; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + synchronized (this) { + ActiveAdmin admin = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + if (admin.disableContactsSearch != disabled) { + admin.disableContactsSearch = disabled; + saveSettingsLocked(mInjector.userHandleGetCallingUserId()); + } + } + } + + @Override + public boolean getCrossProfileContactsSearchDisabled(ComponentName who) { + if (!mHasFeature) { + return false; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + synchronized (this) { + ActiveAdmin admin = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + return admin.disableContactsSearch; + } + } + + @Override + public boolean getCrossProfileContactsSearchDisabledForUser(int userId) { + enforceCrossUsersPermission(userId); + synchronized (this) { + ActiveAdmin admin = getProfileOwnerAdminLocked(userId); + return (admin != null) ? admin.disableContactsSearch : false; + } + } + + @Override public void startManagedQuickContact(String actualLookupKey, long actualContactId, long actualDirectoryId, Intent originalIntent) { final Intent intent = QuickContact.rebuildManagedQuickContactsIntent( diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java index 2e0866cc130a..5abb6e7d9367 100644 --- a/services/print/java/com/android/server/print/PrintManagerService.java +++ b/services/print/java/com/android/server/print/PrintManagerService.java @@ -555,8 +555,14 @@ public final class PrintManagerService extends SystemService { // to handle it as the change may affect ongoing print jobs. UserState userState = getOrCreateUserStateLocked(getChangingUserId()); boolean stoppedSomePackages = false; - Iterator<PrintServiceInfo> iterator = userState.getEnabledPrintServices() - .iterator(); + + List<PrintServiceInfo> enabledServices = userState + .getEnabledPrintServices(); + if (enabledServices == null) { + return false; + } + + Iterator<PrintServiceInfo> iterator = enabledServices.iterator(); while (iterator.hasNext()) { ComponentName componentName = iterator.next().getComponentName(); String componentPackage = componentName.getPackageName(); diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java index 41982170c84c..78edc4df08fa 100644 --- a/services/print/java/com/android/server/print/UserState.java +++ b/services/print/java/com/android/server/print/UserState.java @@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.GET_META_DATA; import static android.content.pm.PackageManager.GET_SERVICES; import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; +import android.annotation.Nullable; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -336,7 +337,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { mSpooler.setPrintJobState(printJobId, PrintJobInfo.STATE_QUEUED, null); } - public List<PrintServiceInfo> getEnabledPrintServices() { + public @Nullable List<PrintServiceInfo> getEnabledPrintServices() { synchronized (mLock) { List<PrintServiceInfo> enabledServices = null; final int installedServiceCount = mInstalledServices.size(); |