diff options
26 files changed, 319 insertions, 213 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 7a20929..dd3d3a8 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -2359,7 +2359,7 @@ public class AccountManager { intent.setClassName(componentName.getPackageName(), componentName.getClassName()); intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ALLOWABLE_ACCOUNTS_ARRAYLIST, - new ArrayList<Account>(allowableAccounts)); + allowableAccounts == null ? null : new ArrayList<Account>(allowableAccounts)); intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY, allowableAccountTypes); intent.putExtra(ChooseTypeAndAccountActivity.EXTRA_ADD_ACCOUNT_OPTIONS_BUNDLE, diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java index 24596c3..b039fc7 100644 --- a/core/java/android/inputmethodservice/ExtractEditText.java +++ b/core/java/android/inputmethodservice/ExtractEditText.java @@ -29,7 +29,7 @@ import android.widget.EditText; public class ExtractEditText extends EditText { private InputMethodService mIME; private int mSettingExtractedText; - + public ExtractEditText(Context context) { super(context, null); } @@ -45,11 +45,11 @@ public class ExtractEditText extends EditText { public ExtractEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } - + void setIME(InputMethodService ime) { mIME = ime; } - + /** * Start making changes that will not be reported to the client. That * is, {@link #onSelectionChanged(int, int)} will not result in sending @@ -58,7 +58,7 @@ public class ExtractEditText extends EditText { public void startInternalChanges() { mSettingExtractedText += 1; } - + /** * Finish making changes that will not be reported to the client. That * is, {@link #onSelectionChanged(int, int)} will not result in sending @@ -67,7 +67,7 @@ public class ExtractEditText extends EditText { public void finishInternalChanges() { mSettingExtractedText -= 1; } - + /** * Implement just to keep track of when we are setting text from the * client (vs. seeing changes in ourself from the user). @@ -80,7 +80,7 @@ public class ExtractEditText extends EditText { mSettingExtractedText--; } } - + /** * Report to the underlying text editor about selection changes. */ @@ -89,7 +89,7 @@ public class ExtractEditText extends EditText { mIME.onExtractedSelectionChanged(selStart, selEnd); } } - + /** * Redirect clicks to the IME for handling there. First allows any * on click handler to run, though. @@ -101,9 +101,10 @@ public class ExtractEditText extends EditText { } return false; } - + @Override public boolean onTextContextMenuItem(int id) { - if (mIME != null && mIME.onExtractTextContextMenuItem(id)) { + // Select all shouldn't be handled by the original edit text, but by the extracted one. + if (id != android.R.id.selectAll && mIME != null && mIME.onExtractTextContextMenuItem(id)) { // Mode was started on Extracted, needs to be stopped here. // Cut will change the text, which stops selection mode. if (id == android.R.id.copy || id == android.R.id.paste) stopTextActionMode(); @@ -111,7 +112,7 @@ public class ExtractEditText extends EditText { } return super.onTextContextMenuItem(id); } - + /** * We are always considered to be an input method target. */ @@ -119,14 +120,14 @@ public class ExtractEditText extends EditText { public boolean isInputMethodTarget() { return true; } - + /** * Return true if the edit text is currently showing a scroll bar. */ public boolean hasVerticalScrollBar() { return computeVerticalScrollRange() > computeVerticalScrollExtent(); } - + /** * Pretend like the window this view is in always has focus, so its * highlight and cursor will be displayed. diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 140f317..320aa2c 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -950,7 +950,7 @@ public class StorageManager { || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) { final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(), vol.getInternalPath(), path); - if (internalPath != null) { + if (internalPath != null && internalPath.exists()) { return internalPath; } } diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index 45cc8b2..1a1e0b2 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -95,8 +95,7 @@ public class KernelUidCpuTimeReader { powerDeltaMaUs -= mLastPowerMaUs.valueAt(index); final long timeDiffUs = nowUs - mLastTimeReadUs; - if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0 || - userTimeDeltaUs > timeDiffUs || systemTimeDeltaUs > timeDiffUs) { + if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0) { StringBuilder sb = new StringBuilder("Malformed cpu data for UID="); sb.append(uid).append("!\n"); sb.append("Time between reads: "); diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java index ef2fef0..41628d0 100644 --- a/core/java/com/android/internal/view/FloatingActionMode.java +++ b/core/java/com/android/internal/view/FloatingActionMode.java @@ -41,13 +41,13 @@ public class FloatingActionMode extends ActionMode { private final ActionMode.Callback2 mCallback; private final MenuBuilder mMenu; private final Rect mContentRect; - private final Rect mContentRectOnWindow; - private final Rect mPreviousContentRectOnWindow; - private final int[] mViewPosition; - private final int[] mPreviousViewPosition; - private final int[] mRootViewPosition; - private final Rect mViewRect; - private final Rect mPreviousViewRect; + private final Rect mContentRectOnScreen; + private final Rect mPreviousContentRectOnScreen; + private final int[] mViewPositionOnScreen; + private final int[] mPreviousViewPositionOnScreen; + private final int[] mRootViewPositionOnScreen; + private final Rect mViewRectOnScreen; + private final Rect mPreviousViewRectOnScreen; private final Rect mScreenRect; private final View mOriginatingView; private final int mBottomAllowance; @@ -77,16 +77,16 @@ public class FloatingActionMode extends ActionMode { MenuItem.SHOW_AS_ACTION_IF_ROOM); setType(ActionMode.TYPE_FLOATING); mContentRect = new Rect(); - mContentRectOnWindow = new Rect(); - mPreviousContentRectOnWindow = new Rect(); - mViewPosition = new int[2]; - mPreviousViewPosition = new int[2]; - mRootViewPosition = new int[2]; - mViewRect = new Rect(); - mPreviousViewRect = new Rect(); + mContentRectOnScreen = new Rect(); + mPreviousContentRectOnScreen = new Rect(); + mViewPositionOnScreen = new int[2]; + mPreviousViewPositionOnScreen = new int[2]; + mRootViewPositionOnScreen = new int[2]; + mViewRectOnScreen = new Rect(); + mPreviousViewRectOnScreen = new Rect(); mScreenRect = new Rect(); mOriginatingView = Preconditions.checkNotNull(originatingView); - mOriginatingView.getLocationInWindow(mViewPosition); + mOriginatingView.getLocationOnScreen(mViewPositionOnScreen); // Allow the content rect to overshoot a little bit beyond the // bottom view bound if necessary. mBottomAllowance = context.getResources() @@ -138,52 +138,53 @@ public class FloatingActionMode extends ActionMode { public void updateViewLocationInWindow() { checkToolbarInitialized(); - mOriginatingView.getLocationInWindow(mViewPosition); - mOriginatingView.getRootView().getLocationInWindow(mRootViewPosition); - mOriginatingView.getGlobalVisibleRect(mViewRect); - mViewRect.offset(mRootViewPosition[0], mRootViewPosition[1]); + mOriginatingView.getLocationOnScreen(mViewPositionOnScreen); + mOriginatingView.getRootView().getLocationOnScreen(mRootViewPositionOnScreen); + mOriginatingView.getGlobalVisibleRect(mViewRectOnScreen); + mViewRectOnScreen.offset(mRootViewPositionOnScreen[0], mRootViewPositionOnScreen[1]); - if (!Arrays.equals(mViewPosition, mPreviousViewPosition) - || !mViewRect.equals(mPreviousViewRect)) { + if (!Arrays.equals(mViewPositionOnScreen, mPreviousViewPositionOnScreen) + || !mViewRectOnScreen.equals(mPreviousViewRectOnScreen)) { repositionToolbar(); - mPreviousViewPosition[0] = mViewPosition[0]; - mPreviousViewPosition[1] = mViewPosition[1]; - mPreviousViewRect.set(mViewRect); + mPreviousViewPositionOnScreen[0] = mViewPositionOnScreen[0]; + mPreviousViewPositionOnScreen[1] = mViewPositionOnScreen[1]; + mPreviousViewRectOnScreen.set(mViewRectOnScreen); } } private void repositionToolbar() { checkToolbarInitialized(); - mContentRectOnWindow.set(mContentRect); - mContentRectOnWindow.offset(mViewPosition[0], mViewPosition[1]); + mContentRectOnScreen.set(mContentRect); + mContentRectOnScreen.offset(mViewPositionOnScreen[0], mViewPositionOnScreen[1]); if (isContentRectWithinBounds()) { mFloatingToolbarVisibilityHelper.setOutOfBounds(false); // Make sure that content rect is not out of the view's visible bounds. - mContentRectOnWindow.set( - Math.max(mContentRectOnWindow.left, mViewRect.left), - Math.max(mContentRectOnWindow.top, mViewRect.top), - Math.min(mContentRectOnWindow.right, mViewRect.right), - Math.min(mContentRectOnWindow.bottom, mViewRect.bottom + mBottomAllowance)); - - if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) { + mContentRectOnScreen.set( + Math.max(mContentRectOnScreen.left, mViewRectOnScreen.left), + Math.max(mContentRectOnScreen.top, mViewRectOnScreen.top), + Math.min(mContentRectOnScreen.right, mViewRectOnScreen.right), + Math.min(mContentRectOnScreen.bottom, + mViewRectOnScreen.bottom + mBottomAllowance)); + + if (!mContentRectOnScreen.equals(mPreviousContentRectOnScreen)) { // Content rect is moving. mOriginatingView.removeCallbacks(mMovingOff); mFloatingToolbarVisibilityHelper.setMoving(true); mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); - mFloatingToolbar.setContentRect(mContentRectOnWindow); + mFloatingToolbar.setContentRect(mContentRectOnScreen); mFloatingToolbar.updateLayout(); } } else { mFloatingToolbarVisibilityHelper.setOutOfBounds(true); mFloatingToolbarVisibilityHelper.updateToolbarVisibility(); - mContentRectOnWindow.setEmpty(); + mContentRectOnScreen.setEmpty(); } - mPreviousContentRectOnWindow.set(mContentRectOnWindow); + mPreviousContentRectOnScreen.set(mContentRectOnScreen); } private boolean isContentRectWithinBounds() { @@ -193,8 +194,8 @@ public class FloatingActionMode extends ActionMode { mContext.getResources().getDisplayMetrics().widthPixels, mContext.getResources().getDisplayMetrics().heightPixels); - return Rect.intersects(mContentRectOnWindow, mScreenRect) - && Rect.intersects(mContentRectOnWindow, mViewRect); + return Rect.intersects(mContentRectOnScreen, mScreenRect) + && Rect.intersects(mContentRectOnScreen, mViewRectOnScreen); } @Override @@ -269,7 +270,6 @@ public class FloatingActionMode extends ActionMode { mOriginatingView.removeCallbacks(mHideOff); } - /** * A helper for showing/hiding the floating toolbar depending on certain states. */ diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index a6e8034..b3f688b 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -285,6 +285,7 @@ public final class FloatingToolbar { private final Context mContext; private final View mParent; + private final int[] mParentPositionOnScreen = new int[2]; private final PopupWindow mPopupWindow; private final ViewGroup mContentContainer; private final int mMarginHorizontal; @@ -337,8 +338,8 @@ public final class FloatingToolbar { } }; - private final Rect mViewPort = new Rect(); - private final Point mCoords = new Point(); + private final Rect mViewPortOnScreen = new Rect(); + private final Point mCoordsOnScreen = new Point(); private final Rect mTmpRect = new Rect(); private final Region mTouchableRegion = new Region(); @@ -428,8 +429,8 @@ public final class FloatingToolbar { * Shows this popup at the specified coordinates. * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. */ - public void show(Rect contentRect) { - Preconditions.checkNotNull(contentRect); + public void show(Rect contentRectOnScreen) { + Preconditions.checkNotNull(contentRectOnScreen); if (isShowing()) { return; @@ -447,9 +448,15 @@ public final class FloatingToolbar { // The "show" animation will make this visible. mContentContainer.setAlpha(0); } - refreshCoordinatesAndOverflowDirection(contentRect); + refreshCoordinatesAndOverflowDirection(contentRectOnScreen); preparePopupContent(); - mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y); + // We need to specify the offset relative to mParent. + // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can + // specify the popup poision in screen coordinates. + mParent.getLocationOnScreen(mParentPositionOnScreen); + final int relativeX = mCoordsOnScreen.x - mParentPositionOnScreen[0]; + final int relativeY = mCoordsOnScreen.y - mParentPositionOnScreen[1]; + mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, relativeX, relativeY); setTouchableSurfaceInsetsComputer(); runShowAnimation(); } @@ -502,17 +509,23 @@ public final class FloatingToolbar { * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. * This is a no-op if this popup is not showing. */ - public void updateCoordinates(Rect contentRect) { - Preconditions.checkNotNull(contentRect); + public void updateCoordinates(Rect contentRectOnScreen) { + Preconditions.checkNotNull(contentRectOnScreen); if (!isShowing() || !mPopupWindow.isShowing()) { return; } cancelOverflowAnimations(); - refreshCoordinatesAndOverflowDirection(contentRect); + refreshCoordinatesAndOverflowDirection(contentRectOnScreen); preparePopupContent(); - mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight()); + // We need to specify the offset relative to mParent. + // TODO: Consider to use PopupWindow.setLayoutInScreenEnabled(true) so that we can + // specify the popup poision in screen coordinates. + mParent.getLocationOnScreen(mParentPositionOnScreen); + final int relativeX = mCoordsOnScreen.x - mParentPositionOnScreen[0]; + final int relativeY = mCoordsOnScreen.y - mParentPositionOnScreen[1]; + mPopupWindow.update(relativeX, relativeY, getWidth(), getHeight()); } /** @@ -536,47 +549,47 @@ public final class FloatingToolbar { return mContext; } - private void refreshCoordinatesAndOverflowDirection(Rect contentRect) { + private void refreshCoordinatesAndOverflowDirection(Rect contentRectOnScreen) { refreshViewPort(); - int x = contentRect.centerX() - getWidth() / 2; + int x = contentRectOnScreen.centerX() - getWidth() / 2; // Update x so that the toolbar isn't rendered behind the nav bar in landscape. - x = Math.max(0, Math.min(x, mViewPort.right - getWidth())); + x = Math.max(0, Math.min(x, mViewPortOnScreen.right - getWidth())); int y; - int availableHeightAboveContent = contentRect.top - mViewPort.top; - int availableHeightBelowContent = mViewPort.bottom - contentRect.bottom; + int availableHeightAboveContent = contentRectOnScreen.top - mViewPortOnScreen.top; + int availableHeightBelowContent = mViewPortOnScreen.bottom - contentRectOnScreen.bottom; if (mOverflowPanel == null) { // There is no overflow. if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin()) { // There is enough space at the top of the content. - y = contentRect.top - getToolbarHeightWithVerticalMargin(); + y = contentRectOnScreen.top - getToolbarHeightWithVerticalMargin(); } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin()) { // There is enough space at the bottom of the content. - y = contentRect.bottom; + y = contentRectOnScreen.bottom; } else if (availableHeightBelowContent >= getEstimatedToolbarHeight(mContext)) { // Just enough space to fit the toolbar with no vertical margins. - y = contentRect.bottom - mMarginVertical; + y = contentRectOnScreen.bottom - mMarginVertical; } else { // Not enough space. Prefer to position as high as possible. y = Math.max( - mViewPort.top, - contentRect.top - getToolbarHeightWithVerticalMargin()); + mViewPortOnScreen.top, + contentRectOnScreen.top - getToolbarHeightWithVerticalMargin()); } } else { // There is an overflow. int margin = 2 * mMarginVertical; int minimumOverflowHeightWithMargin = mOverflowPanel.getMinimumHeight() + margin; - int availableHeightThroughContentDown = - mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin(); - int availableHeightThroughContentUp = - contentRect.bottom - mViewPort.top + getToolbarHeightWithVerticalMargin(); + int availableHeightThroughContentDown = mViewPortOnScreen.bottom - + contentRectOnScreen.top + getToolbarHeightWithVerticalMargin(); + int availableHeightThroughContentUp = contentRectOnScreen.bottom - + mViewPortOnScreen.top + getToolbarHeightWithVerticalMargin(); if (availableHeightAboveContent >= minimumOverflowHeightWithMargin) { // There is enough space at the top of the content rect for the overflow. // Position above and open upwards. updateOverflowHeight(availableHeightAboveContent - margin); - y = contentRect.top - getHeight(); + y = contentRectOnScreen.top - getHeight(); mOverflowDirection = OVERFLOW_DIRECTION_UP; } else if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin() && availableHeightThroughContentDown >= minimumOverflowHeightWithMargin) { @@ -584,33 +597,34 @@ public final class FloatingToolbar { // but not the overflow. // Position above but open downwards. updateOverflowHeight(availableHeightThroughContentDown - margin); - y = contentRect.top - getToolbarHeightWithVerticalMargin(); + y = contentRectOnScreen.top - getToolbarHeightWithVerticalMargin(); mOverflowDirection = OVERFLOW_DIRECTION_DOWN; } else if (availableHeightBelowContent >= minimumOverflowHeightWithMargin) { // There is enough space at the bottom of the content rect for the overflow. // Position below and open downwards. updateOverflowHeight(availableHeightBelowContent - margin); - y = contentRect.bottom; + y = contentRectOnScreen.bottom; mOverflowDirection = OVERFLOW_DIRECTION_DOWN; } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin() - && mViewPort.height() >= minimumOverflowHeightWithMargin) { + && mViewPortOnScreen.height() >= minimumOverflowHeightWithMargin) { // There is enough space at the bottom of the content rect for the main panel // but not the overflow. // Position below but open upwards. updateOverflowHeight(availableHeightThroughContentUp - margin); - y = contentRect.bottom + getToolbarHeightWithVerticalMargin() - getHeight(); + y = contentRectOnScreen.bottom + getToolbarHeightWithVerticalMargin() - + getHeight(); mOverflowDirection = OVERFLOW_DIRECTION_UP; } else { // Not enough space. // Position at the top of the view port and open downwards. - updateOverflowHeight(mViewPort.height() - margin); - y = mViewPort.top; + updateOverflowHeight(mViewPortOnScreen.height() - margin); + y = mViewPortOnScreen.top; mOverflowDirection = OVERFLOW_DIRECTION_DOWN; } mOverflowPanel.setOverflowDirection(mOverflowDirection); } - mCoords.set(x, y); + mCoordsOnScreen.set(x, y); } private int getToolbarHeightWithVerticalMargin() { @@ -913,18 +927,18 @@ public final class FloatingToolbar { private void refreshViewPort() { - mParent.getWindowVisibleDisplayFrame(mViewPort); + mParent.getWindowVisibleDisplayFrame(mViewPortOnScreen); } private boolean viewPortHasChanged() { mParent.getWindowVisibleDisplayFrame(mTmpRect); - return !mTmpRect.equals(mViewPort); + return !mTmpRect.equals(mViewPortOnScreen); } private int getToolbarWidth(int suggestedWidth) { int width = suggestedWidth; refreshViewPort(); - int maximumWidth = mViewPort.width() - 2 * mParent.getResources() + int maximumWidth = mViewPortOnScreen.width() - 2 * mParent.getResources() .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); if (width <= 0) { width = mParent.getResources() @@ -1443,6 +1457,9 @@ public final class FloatingToolbar { private static PopupWindow createPopupWindow(View content) { ViewGroup popupContentHolder = new LinearLayout(content.getContext()); PopupWindow popupWindow = new PopupWindow(popupContentHolder); + // TODO: Use .setLayoutInScreenEnabled(true) instead of .setClippingEnabled(false) + // unless FLAG_LAYOUT_IN_SCREEN has any unintentional side-effects. + popupWindow.setClippingEnabled(false); popupWindow.setWindowLayoutType( WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL); popupWindow.setAnimationStyle(0); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 91b6348..d3117b9 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1041,7 +1041,7 @@ --> <permission android:name="android.permission.GET_ACCOUNTS" android:permissionGroup="android.permission-group.CONTACTS" - android:protectionLevel="normal" + android:protectionLevel="dangerous" android:description="@string/permdesc_getAccounts" android:label="@string/permlab_getAccounts" /> diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index 7c9b30b..26232a9 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -21,6 +21,7 @@ import android.annotation.DrawableRes; import android.content.res.ColorStateList; import android.content.ContentResolver; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Bitmap; @@ -294,7 +295,13 @@ public final class Icon implements Parcelable { } else { final PackageManager pm = context.getPackageManager(); try { - mObj1 = pm.getResourcesForApplication(resPackage); + ApplicationInfo ai = pm.getApplicationInfo( + resPackage, PackageManager.GET_UNINSTALLED_PACKAGES); + if (ai != null) { + mObj1 = pm.getResourcesForApplication(ai); + } else { + break; + } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, String.format("Unable to find pkg=%s for icon %s", resPackage, this), e); diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java index 515be1d..5ce4fd2 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java @@ -124,22 +124,27 @@ public class AndroidKeyStoreKeyFactorySpi extends KeyFactorySpi { @Override protected PrivateKey engineGeneratePrivate(KeySpec spec) throws InvalidKeySpecException { - throw new UnsupportedOperationException( - "To generate a key pair in Android KeyStore, use KeyPairGenerator initialized with" + throw new InvalidKeySpecException( + "To generate a key pair in Android Keystore, use KeyPairGenerator initialized with" + " " + KeyGenParameterSpec.class.getName()); } @Override protected PublicKey engineGeneratePublic(KeySpec spec) throws InvalidKeySpecException { - throw new UnsupportedOperationException( - "To generate a key pair in Android KeyStore, use KeyPairGenerator initialized with" + throw new InvalidKeySpecException( + "To generate a key pair in Android Keystore, use KeyPairGenerator initialized with" + " " + KeyGenParameterSpec.class.getName()); } @Override - protected Key engineTranslateKey(Key arg0) throws InvalidKeyException { - throw new UnsupportedOperationException( - "To import a key into Android KeyStore, use KeyStore.setEntry with " - + KeyProtection.class.getName()); + protected Key engineTranslateKey(Key key) throws InvalidKeyException { + if (key == null) { + throw new InvalidKeyException("key == null"); + } else if ((!(key instanceof AndroidKeyStorePrivateKey)) + && (!(key instanceof AndroidKeyStorePublicKey))) { + throw new InvalidKeyException( + "To import a key into Android Keystore, use KeyStore.setEntry"); + } + return key; } } diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java index 9a2f908..11c22a9 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java @@ -185,15 +185,20 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { @Override protected SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException { - throw new UnsupportedOperationException( - "To generate secret key in Android KeyStore, use KeyGenerator initialized with " + throw new InvalidKeySpecException( + "To generate secret key in Android Keystore, use KeyGenerator initialized with " + KeyGenParameterSpec.class.getName()); } @Override protected SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException { - throw new UnsupportedOperationException( - "To import a secret key into Android KeyStore, use KeyStore.setEntry with " - + KeyProtection.class.getName()); + if (key == null) { + throw new InvalidKeyException("key == null"); + } else if (!(key instanceof AndroidKeyStoreSecretKey)) { + throw new InvalidKeyException( + "To import a secret key into Android Keystore, use KeyStore.setEntry"); + } + + return key; } } diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 2cfb9e1..a2aa2d1 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -370,7 +370,11 @@ void SkiaShader::store(Caches& caches, const SkShader& shader, const Matrix4& mo if (tryStoreLayer(caches, shader, modelViewMatrix, textureUnit, description, &outData->layerData)) { outData->skiaShaderType = kLayer_SkiaShaderType; + return; } + + // Unknown/unsupported type, so explicitly ignore shader + outData->skiaShaderType = kNone_SkiaShaderType; } void SkiaShader::apply(Caches& caches, const SkiaShaderData& data) { diff --git a/libs/hwui/renderstate/TextureState.cpp b/libs/hwui/renderstate/TextureState.cpp index a211de7..987d4cd 100644 --- a/libs/hwui/renderstate/TextureState.cpp +++ b/libs/hwui/renderstate/TextureState.cpp @@ -22,7 +22,8 @@ namespace uirenderer { const GLenum kTextureUnits[] = { GL_TEXTURE0, GL_TEXTURE1, - GL_TEXTURE2 + GL_TEXTURE2, + GL_TEXTURE3 }; TextureState::TextureState() @@ -33,10 +34,13 @@ TextureState::TextureState() GLint maxTextureUnits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); LOG_ALWAYS_FATAL_IF(maxTextureUnits < kTextureUnitsCount, - "At least %d texture units are required!", kTextureUnitsCount); + "At least %d texture units are required!", kTextureUnitsCount); } void TextureState::activateTexture(GLuint textureUnit) { + LOG_ALWAYS_FATAL_IF(textureUnit >= kTextureUnitsCount, + "Tried to use texture unit index %d, only %d exist", + textureUnit, kTextureUnitsCount); if (mTextureUnit != textureUnit) { glActiveTexture(kTextureUnits[textureUnit]); mTextureUnit = textureUnit; diff --git a/libs/hwui/renderstate/TextureState.h b/libs/hwui/renderstate/TextureState.h index 5a57b9f..d3c014c 100644 --- a/libs/hwui/renderstate/TextureState.h +++ b/libs/hwui/renderstate/TextureState.h @@ -73,7 +73,7 @@ public: void unbindTexture(GLuint texture); private: // total number of texture units available for use - static const int kTextureUnitsCount = 3; + static const int kTextureUnitsCount = 4; TextureState(); GLuint mTextureUnit; diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index f42fab7..76d36a0 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -16,6 +16,8 @@ package android.media; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.util.Log; import android.util.Pair; import android.util.Range; @@ -1003,6 +1005,7 @@ public final class MediaCodecInfo { private Range<Rational> mAspectRatioRange; private Range<Rational> mBlockAspectRatioRange; private Range<Long> mBlocksPerSecondRange; + private Map<Size, Range<Long>> mMeasuredFrameRates; private Range<Integer> mFrameRateRange; private int mBlockWidth; @@ -1195,6 +1198,28 @@ public final class MediaCodecInfo { (double) mFrameRateRange.getUpper())); } + @NonNull + private Size findClosestSize(int width, int height) { + int targetPixels = width * height; + Size closestSize = null; + int mimPixelsDiff = Integer.MAX_VALUE; + for (Size size : mMeasuredFrameRates.keySet()) { + int pixelsDiff = Math.abs(targetPixels - size.getWidth() * size.getHeight()); + if (pixelsDiff < mimPixelsDiff) { + mimPixelsDiff = pixelsDiff; + closestSize = size; + } + } + return closestSize; + } + + private Range<Double> estimateFrameRatesFor(int width, int height) { + Size size = findClosestSize(width, height); + Range<Long> range = mMeasuredFrameRates.get(size); + Double ratio = (double)(width * height) / (size.getWidth() * size.getHeight()); + return Range.create(range.getLower() * ratio, range.getUpper() * ratio); + } + /** * Returns the range of achievable video frame rates for a video size. * May return {@code null}, if the codec did not publish any measurement @@ -1208,12 +1233,18 @@ public final class MediaCodecInfo { * * @throws IllegalArgumentException if the video size is not supported. */ + @Nullable public Range<Double> getAchievableFrameRatesFor(int width, int height) { if (!supports(width, height, null)) { throw new IllegalArgumentException("unsupported size"); } - // TODO: get this data from the codec - return null; + + if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) { + Log.w(TAG, "Codec did not publish any measurement data."); + return null; + } + + return estimateFrameRatesFor(width, height); } /** @@ -1346,6 +1377,34 @@ public final class MediaCodecInfo { mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper(); } + private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) { + Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>(); + final String prefix = "measured-frame-rate-"; + Set<String> keys = map.keySet(); + for (String key : keys) { + // looking for: measured-frame-rate-WIDTHxHEIGHT-range + if (!key.startsWith(prefix)) { + continue; + } + String subKey = key.substring(prefix.length()); + String[] temp = key.split("-"); + if (temp.length != 5) { + continue; + } + String sizeStr = temp[3]; + Size size = Utils.parseSize(sizeStr, null); + if (size == null || size.getWidth() * size.getHeight() <= 0) { + continue; + } + Range<Long> range = Utils.parseLongRange(map.get(key), null); + if (range == null || range.getLower() < 0 || range.getUpper() < 0) { + continue; + } + ret.put(size, range); + } + return ret; + } + private void parseFromInfo(MediaFormat info) { final Map<String, Object> map = info.getMap(); Size blockSize = new Size(mBlockWidth, mBlockHeight); @@ -1360,6 +1419,7 @@ public final class MediaCodecInfo { counts = Utils.parseIntRange(map.get("block-count-range"), null); blockRates = Utils.parseLongRange(map.get("blocks-per-second-range"), null); + mMeasuredFrameRates = getMeasuredFrameRates(map); { Object o = map.get("size-range"); Pair<Size, Size> sizeRange = Utils.parseSizeRange(o); diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 377a9a4..b03f100 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -182,4 +182,17 @@ <!-- Message for the error dialog when BT pairing fails because the other device rejected the pairing. --> <string name="bluetooth_pairing_rejected_error_message">Pairing rejected by <xliff:g id="device_name">%1$s</xliff:g>.</string> + <!-- Content description of the WIFI signal when WIFI is disabled for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_off">Wifi off.</string> + <!-- Content description of the WIFI signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_wifi">Wifi disconnected.</string> + <!-- Content description of the WIFI signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_one_bar">Wifi one bar.</string> + <!-- Content description of the WIFI signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_two_bars">Wifi two bars.</string> + <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_three_bars">Wifi three bars.</string> + <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_wifi_signal_full">Wifi signal full.</string> + </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d32ce55..fcf7e3e 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -276,19 +276,6 @@ <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_data_signal_full">Data signal full.</string> - <!-- Content description of the WIFI signal when WIFI is disabled for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_wifi_off">Wifi off.</string> - <!-- Content description of the WIFI signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_no_wifi">Wifi disconnected.</string> - <!-- Content description of the WIFI signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_wifi_one_bar">Wifi one bar.</string> - <!-- Content description of the WIFI signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_wifi_two_bars">Wifi two bars.</string> - <!-- Content description of the WIFI signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_wifi_three_bars">Wifi three bars.</string> - <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_wifi_signal_full">Wifi signal full.</string> - <!-- Content description of the wifi label showing what we are connected to. [CHAR LIMIT=NONE] --> <string name="accessibility_wifi_name">Connected to <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string> diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 2ded919..94d5170 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -158,6 +158,9 @@ public class QSPanel extends ViewGroup { mColumns = columns; postInvalidate(); } + for (TileRecord r : mRecords) { + r.tile.clearState(); + } if (mListening) { refreshAllTiles(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index 38fade2..b330582 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -61,8 +61,8 @@ public abstract class QSTile<TState extends State> implements Listenable { protected final Handler mUiHandler = new Handler(Looper.getMainLooper()); private Callback mCallback; - protected final TState mState = newTileState(); - private final TState mTmpState = newTileState(); + protected TState mState = newTileState(); + private TState mTmpState = newTileState(); private boolean mAnnounceNextStateChange; abstract protected TState newTileState(); @@ -139,6 +139,10 @@ public abstract class QSTile<TState extends State> implements Listenable { mHandler.obtainMessage(H.REFRESH_STATE, arg).sendToTarget(); } + public final void clearState() { + mHandler.sendEmptyMessage(H.CLEAR_STATE); + } + public void userSwitch(int newUserId) { mHandler.obtainMessage(H.USER_SWITCH, newUserId, 0).sendToTarget(); } @@ -178,6 +182,11 @@ public abstract class QSTile<TState extends State> implements Listenable { // optional } + protected void handleClearState() { + mTmpState = newTileState(); + mState = newTileState(); + } + protected void handleRefreshState(Object arg) { handleUpdateState(mTmpState, arg); final boolean changed = mTmpState.copyTo(mState); @@ -246,6 +255,7 @@ public abstract class QSTile<TState extends State> implements Listenable { private static final int TOGGLE_STATE_CHANGED = 8; private static final int SCAN_STATE_CHANGED = 9; private static final int DESTROY = 10; + private static final int CLEAR_STATE = 11; private H(Looper looper) { super(looper); @@ -286,6 +296,9 @@ public abstract class QSTile<TState extends State> implements Listenable { } else if (msg.what == DESTROY) { name = "handleDestroy"; handleDestroy(); + } else if (msg.what == CLEAR_STATE) { + name = "handleClearState"; + handleClearState(); } else { throw new IllegalArgumentException("Unknown msg: " + msg.what); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 9343172..889160d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -658,11 +658,6 @@ public abstract class PanelView extends FrameLayout { (animator.getDuration() * getCannedFlingDurationFactor() / collapseSpeedUpFactor)); } - if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD - && mStatusBar.getBarState() == StatusBarState.KEYGUARD) { - Log.i(PhoneStatusBar.TAG, "Panel collapsed! Stacktrace: " - + Log.getStackTraceString(new Throwable())); - } } animator.addListener(new AnimatorListenerAdapter() { private boolean mCancelled; @@ -777,15 +772,6 @@ public abstract class PanelView extends FrameLayout { public void setExpandedFraction(float frac) { setExpandedHeight(getMaxPanelHeight() * frac); - if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD - && mStatusBar.getBarState() == StatusBarState.KEYGUARD) { - if (frac == 0.0f) { - Log.i(PhoneStatusBar.TAG, "Panel collapsed! Stacktrace: " - + Log.getStackTraceString(new Throwable())); - } else if (frac == 1.0f) { - mStatusBar.endWindowManagerLogging(); - } - } } public float getExpandedHeight() { @@ -817,11 +803,6 @@ public abstract class PanelView extends FrameLayout { } public void collapse(boolean delayed, float speedUpFactor) { - if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD - && mStatusBar.getBarState() == StatusBarState.KEYGUARD) { - Log.i(PhoneStatusBar.TAG, "Panel collapsed! Stacktrace: " - + Log.getStackTraceString(new Throwable())); - } if (DEBUG) logf("collapse: " + this); if (mPeekPending || mPeekAnimator != null) { mCollapseAfterPeek = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index f0e50f8..88aa071 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -185,7 +185,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, HeadsUpManager.OnHeadsUpChangedListener { static final String TAG = "PhoneStatusBar"; public static final boolean DEBUG = BaseStatusBar.DEBUG; - public static final boolean DEBUG_EMPTY_KEYGUARD = true; public static final boolean SPEW = false; public static final boolean DUMPTRUCK = true; // extra dumpsys info public static final boolean DEBUG_GESTURES = false; @@ -2009,10 +2008,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowManager.setPanelExpanded(isExpanded); } - public void endWindowManagerLogging() { - mStatusBarWindowManager.setLogState(false); - } - /** * All changes to the status bar and notifications funnel through here and are batched. */ @@ -2675,7 +2670,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, pw.print(" status bar gestures: "); mGestureRec.dump(fd, pw, args); } - + if (mStatusBarWindowManager != null) { + mStatusBarWindowManager.dump(fd, pw, args); + } if (mNetworkController != null) { mNetworkController.dump(fd, pw, args); } @@ -3592,9 +3589,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Make our window larger and the panel expanded. makeExpandedVisible(true); mNotificationPanel.instantExpand(); - if (DEBUG_EMPTY_KEYGUARD) { - mStatusBarWindowManager.setLogState(true); - } } private void instantCollapseNotificationPanel() { 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 6a46924..6d04b28 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -20,14 +20,12 @@ import android.content.Context; import android.content.res.Resources; import android.util.AttributeSet; import android.util.EventLog; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; import com.android.systemui.EventLogTags; import com.android.systemui.R; -import com.android.systemui.statusbar.StatusBarState; public class PhoneStatusBarView extends PanelBar { private static final String TAG = "PhoneStatusBarView"; @@ -118,11 +116,6 @@ public class PhoneStatusBarView extends PanelBar { @Override public void onAllPanelsCollapsed() { super.onAllPanelsCollapsed(); - if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD - && mBar.getBarState() == StatusBarState.KEYGUARD) { - Log.i(PhoneStatusBar.TAG, "Panel collapsed! Stacktrace: " - + Log.getStackTraceString(new Throwable())); - } // Close the status bar in the next frame so we can show the end of the animation. postOnAnimation(mHideExpandedRunnable); mLastFullyOpenedPanel = null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index 0d816dd..038fefb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -21,7 +21,6 @@ import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.SystemProperties; -import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -32,6 +31,8 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.StatusBarState; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.lang.reflect.Field; /** @@ -48,7 +49,6 @@ public class StatusBarWindowManager { private final boolean mKeyguardScreenRotation; private final State mCurrentState = new State(); - private boolean mLogState; public StatusBarWindowManager(Context context) { mContext = context; @@ -183,9 +183,6 @@ public class StatusBarWindowManager { applyFitsSystemWindows(state); applyModalFlag(state); if (mLp.copyFrom(mLpChanged) != 0) { - if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD && mLogState) { - logCurrentState(); - } mWindowManager.updateViewLayout(mStatusBarView, mLp); } } @@ -282,19 +279,9 @@ public class StatusBarWindowManager { apply(mCurrentState); } - public void setLogState(boolean logState) { - mLogState = logState; - if (logState) { - Log.w(PhoneStatusBar.TAG, "===== Started logging WM state changes ====="); - logCurrentState(); - } else { - Log.w(PhoneStatusBar.TAG, "===== Finished logging WM state changes ====="); - } - } - - private void logCurrentState() { - Log.i(PhoneStatusBar.TAG, mCurrentState.toString() - + "\n Expanded: " + isExpanded(mCurrentState)); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("StatusBarWindowManager state:"); + pw.println(mCurrentState); } private static class State { diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index bc61c3d..0e158a2 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2602,8 +2602,15 @@ class MountService extends IMountService.Stub boolean foundPrimary = false; final int userId = UserHandle.getUserId(uid); - final boolean reportUnmounted = !mMountServiceInternal.hasExternalStorage( - uid, packageName); + final boolean reportUnmounted; + + final long identity = Binder.clearCallingIdentity(); + try { + reportUnmounted = !mMountServiceInternal.hasExternalStorage( + uid, packageName); + } finally { + Binder.restoreCallingIdentity(identity); + } synchronized (mLock) { for (int i = 0; i < mVolumes.size(); i++) { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index f618c3e..f8f00ef 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -22,6 +22,7 @@ import static android.Manifest.permission.DUMP; import static android.Manifest.permission.MANAGE_NETWORK_POLICY; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.READ_PHONE_STATE; +import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_ADDED; @@ -1651,11 +1652,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @Override public NetworkPolicy[] getNetworkPolicies(String callingPackage) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); - mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); + try { + mContext.enforceCallingPermission(READ_PRIVILEGED_PHONE_STATE, TAG); + // SKIP checking run-time OP_READ_PHONE_STATE since using PRIVILEGED + } catch (SecurityException e) { + mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); - if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(), - callingPackage) != AppOpsManager.MODE_ALLOWED) { - return new NetworkPolicy[0]; + if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(), + callingPackage) != AppOpsManager.MODE_ALLOWED) { + return new NetworkPolicy[0]; + } } synchronized (mRulesLock) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index b23b856..7a6895f 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1837,7 +1837,7 @@ public class NotificationManagerService extends SystemService { void dumpImpl(PrintWriter pw, DumpFilter filter) { pw.print("Current Notification Manager state"); - if (filter != null) { + if (filter.filtered) { pw.print(" (filtered to "); pw.print(filter); pw.print(")"); } pw.println(':'); @@ -1865,7 +1865,7 @@ public class NotificationManagerService extends SystemService { for (int i=0; i<N; i++) { final NotificationRecord nr = mNotificationList.get(i); if (filter != null && !filter.matches(nr.sbn)) continue; - nr.dump(pw, " ", getContext()); + nr.dump(pw, " ", getContext(), filter.redact); } pw.println(" "); } @@ -1948,7 +1948,7 @@ public class NotificationManagerService extends SystemService { pw.println(" " + entry.getKey() + " -> " + r.getKey()); if (mNotificationsByKey.get(r.getKey()) != r) { pw.println("!!!!!!LEAK: Record not found in mNotificationsByKey."); - r.dump(pw, " ", getContext()); + r.dump(pw, " ", getContext(), filter.redact); } } @@ -3499,46 +3499,59 @@ public class NotificationManagerService extends SystemService { } public static final class DumpFilter { + public boolean filtered = false; public String pkgFilter; public boolean zen; public long since; public boolean stats; - private boolean all; + public boolean redact = true; public static DumpFilter parseFromArguments(String[] args) { - if (args != null && args.length == 2 && "p".equals(args[0]) - && args[1] != null && !args[1].trim().isEmpty()) { - final DumpFilter filter = new DumpFilter(); - filter.pkgFilter = args[1].trim().toLowerCase(); - return filter; - } - if (args != null && args.length == 1 && "zen".equals(args[0])) { - final DumpFilter filter = new DumpFilter(); - filter.zen = true; - filter.all = true; - return filter; - } - if (args != null && args.length >= 1 && "--stats".equals(args[0])) { - final DumpFilter filter = new DumpFilter(); - filter.stats = true; - filter.since = args.length == 2 ? Long.valueOf(args[1]) : 0; - filter.all = true; - return filter; + final DumpFilter filter = new DumpFilter(); + for (int ai = 0; ai < args.length; ai++) { + final String a = args[ai]; + if ("--noredact".equals(a) || "--reveal".equals(a)) { + filter.redact = false; + } else if ("p".equals(a) || "pkg".equals(a) || "--package".equals(a)) { + if (ai < args.length-1) { + ai++; + filter.pkgFilter = args[ai].trim().toLowerCase(); + if (filter.pkgFilter.isEmpty()) { + filter.pkgFilter = null; + } else { + filter.filtered = true; + } + } + } else if ("--zen".equals(a) || "zen".equals(a)) { + filter.filtered = true; + filter.zen = true; + } else if ("--stats".equals(a)) { + filter.stats = true; + if (ai < args.length-1) { + ai++; + filter.since = Long.valueOf(args[ai]); + } else { + filter.since = 0; + } + } } - return null; + return filter; } public boolean matches(StatusBarNotification sbn) { - return all ? true : sbn != null + if (!filtered) return true; + return zen ? true : sbn != null && (matches(sbn.getPackageName()) || matches(sbn.getOpPkg())); } public boolean matches(ComponentName component) { - return all ? true : component != null && matches(component.getPackageName()); + if (!filtered) return true; + return zen ? true : component != null && matches(component.getPackageName()); } public boolean matches(String pkg) { - return all ? true : pkg != null && pkg.toLowerCase().contains(pkgFilter); + if (!filtered) return true; + return zen ? true : pkg != null && pkg.toLowerCase().contains(pkgFilter); } @Override diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index b7aea9d..f37702c 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -114,7 +114,7 @@ public final class NotificationRecord { /** @deprecated Use {@link #getUser()} instead. */ public int getUserId() { return sbn.getUserId(); } - void dump(PrintWriter pw, String prefix, Context baseContext) { + void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) { final Notification notification = sbn.getNotification(); final Icon icon = notification.getSmallIcon(); String iconStr = String.valueOf(icon); @@ -164,7 +164,7 @@ public final class NotificationRecord { pw.println("null"); } else { pw.print(val.getClass().getSimpleName()); - if (val instanceof CharSequence || val instanceof String) { + if (redact && (val instanceof CharSequence || val instanceof String)) { // redact contents from bugreports } else if (val instanceof Bitmap) { pw.print(String.format(" (%dx%d)", @@ -172,7 +172,14 @@ public final class NotificationRecord { ((Bitmap) val).getHeight())); } else if (val.getClass().isArray()) { final int N = Array.getLength(val); - pw.println(" (" + N + ")"); + pw.print(" (" + N + ")"); + if (!redact) { + for (int j=0; j<N; j++) { + pw.println(); + pw.print(String.format("%s [%d] %s", + prefix, j, String.valueOf(Array.get(val, j)))); + } + } } else { pw.print(" (" + String.valueOf(val) + ")"); } |