diff options
36 files changed, 266 insertions, 165 deletions
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl index dd2e0066a036..45a38be8aee4 100644 --- a/core/java/com/android/internal/policy/IKeyguardService.aidl +++ b/core/java/com/android/internal/policy/IKeyguardService.aidl @@ -42,4 +42,5 @@ interface IKeyguardService { oneway void setCurrentUser(int userId); oneway void showAssistant(); oneway void dispatch(in MotionEvent event); + oneway void launchCamera(); } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 8adc7b629a3e..860226047d3c 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1260,7 +1260,7 @@ public class LockPatternUtils { * @param upperCase if true, converts button label string to upper case */ public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown, - boolean upperCase, boolean showIcon) { + boolean showIcon) { if (isEmergencyCallCapable() && shown) { button.setVisibility(View.VISIBLE); } else { @@ -1279,23 +1279,7 @@ public class LockPatternUtils { int emergencyIcon = showIcon ? R.drawable.ic_emergency : 0; button.setCompoundDrawablesWithIntrinsicBounds(emergencyIcon, 0, 0, 0); } - if (upperCase) { - CharSequence original = mContext.getResources().getText(textId); - String upper = original != null ? original.toString().toUpperCase() : null; - button.setText(upper); - } else { - button.setText(textId); - } - } - - /** - * @deprecated - * @param button - * @param phoneState - * @param shown - */ - public void updateEmergencyCallButtonState(Button button, int phoneState, boolean shown) { - updateEmergencyCallButtonState(button, phoneState, shown, false, true); + button.setText(textId); } /** diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java index 356401c2a322..e30c1ff37463 100644 --- a/core/java/com/android/internal/widget/SubtitleView.java +++ b/core/java/com/android/internal/widget/SubtitleView.java @@ -31,7 +31,6 @@ import android.graphics.Typeface; import android.text.Layout.Alignment; import android.text.StaticLayout; import android.text.TextPaint; -import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; @@ -52,14 +51,12 @@ public class SubtitleView extends View { /** Temporary rectangle used for computing line bounds. */ private final RectF mLineBounds = new RectF(); - /** Temporary array used for computing line wrapping. */ - private float[] mTextWidths; - /** Reusable string builder used for holding text. */ private final StringBuilder mText = new StringBuilder(); - private final StringBuilder mBreakText = new StringBuilder(); - private TextPaint mPaint; + private Alignment mAlignment; + private TextPaint mTextPaint; + private Paint mPaint; private int mForegroundColor; private int mBackgroundColor; @@ -122,11 +119,12 @@ public class SubtitleView extends View { mShadowOffsetX = res.getDimension(com.android.internal.R.dimen.subtitle_shadow_offset); mShadowOffsetY = mShadowOffsetX; - final TextPaint paint = new TextPaint(); - paint.setAntiAlias(true); - paint.setSubpixelText(true); + mTextPaint = new TextPaint(); + mTextPaint.setAntiAlias(true); + mTextPaint.setSubpixelText(true); - mPaint = paint; + mPaint = new Paint(); + mPaint.setAntiAlias(true); setText(text); setTextSize(textSize); @@ -174,21 +172,30 @@ public class SubtitleView extends View { public void setTextSize(float size) { final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); final float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, metrics); - if (mPaint.getTextSize() != size) { - mHasMeasurements = false; + if (mTextPaint.getTextSize() != size) { + mTextPaint.setTextSize(size); mInnerPaddingX = (int) (size * INNER_PADDING_RATIO + 0.5f); - mPaint.setTextSize(size); - requestLayout(); + mHasMeasurements = false; + forceLayout(); } } public void setTypeface(Typeface typeface) { - if (mPaint.getTypeface() != typeface) { + if (mTextPaint.getTypeface() != typeface) { + mTextPaint.setTypeface(typeface); + mHasMeasurements = false; - mPaint.setTypeface(typeface); + forceLayout(); + } + } - requestLayout(); + public void setAlignment(Alignment textAlignment) { + if (mAlignment != textAlignment) { + mAlignment = textAlignment; + + mHasMeasurements = false; + forceLayout(); } } @@ -222,63 +229,19 @@ public class SubtitleView extends View { } // Account for padding. - final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX; + final int paddingX = mPaddingLeft + mPaddingRight + mInnerPaddingX * 2; maxWidth -= paddingX; - if (maxWidth <= 0) { return false; } - final TextPaint paint = mPaint; - final CharSequence text = mText; - final int textLength = text.length(); - if (mTextWidths == null || mTextWidths.length < textLength) { - mTextWidths = new float[textLength]; - } - - final float[] textWidths = mTextWidths; - paint.getTextWidths(text, 0, textLength, textWidths); - - // Compute total length. - float runLength = 0; - for (int i = 0; i < textLength; i++) { - runLength += textWidths[i]; - } - - final int lineCount = (int) (runLength / maxWidth) + 1; - final int lineLength = (int) (runLength / lineCount); - - // Build line break buffer. - final StringBuilder breakText = mBreakText; - breakText.setLength(0); - - int line = 0; - int lastBreak = 0; - int maxRunLength = 0; - runLength = 0; - for (int i = 0; i < textLength; i++) { - if (runLength > lineLength) { - final CharSequence sequence = text.subSequence(lastBreak, i); - final int trimmedLength = TextUtils.getTrimmedLength(sequence); - breakText.append(sequence, 0, trimmedLength); - breakText.append('\n'); - lastBreak = i; - runLength = 0; - } - - runLength += textWidths[i]; - - if (runLength > maxRunLength) { - maxRunLength = (int) Math.ceil(runLength); - } - } - breakText.append(text.subSequence(lastBreak, textLength)); - + // TODO: Implement minimum-difference line wrapping. Adding the results + // of Paint.getTextWidths() seems to return different values than + // StaticLayout.getWidth(), so this is non-trivial. mHasMeasurements = true; mLastMeasuredWidth = maxWidth; - - mLayout = new StaticLayout(breakText, paint, maxRunLength, Alignment.ALIGN_LEFT, - mSpacingMult, mSpacingAdd, true); + mLayout = new StaticLayout( + mText, mTextPaint, maxWidth, mAlignment, mSpacingMult, mSpacingAdd, true); return true; } @@ -316,54 +279,50 @@ public class SubtitleView extends View { final int innerPaddingX = mInnerPaddingX; c.translate(mPaddingLeft + innerPaddingX, mPaddingTop); - final RectF bounds = mLineBounds; final int lineCount = layout.getLineCount(); - final Paint paint = layout.getPaint(); - paint.setShadowLayer(0, 0, 0, 0); - - final int backgroundColor = mBackgroundColor; - if (Color.alpha(backgroundColor) > 0) { - paint.setColor(backgroundColor); - paint.setStyle(Style.FILL); + final Paint textPaint = mTextPaint; + final Paint paint = mPaint; + final RectF bounds = mLineBounds; + if (Color.alpha(mBackgroundColor) > 0) { final float cornerRadius = mCornerRadius; float previousBottom = layout.getLineTop(0); + paint.setColor(mBackgroundColor); + paint.setStyle(Style.FILL); + for (int i = 0; i < lineCount; i++) { - bounds.left = layout.getLineLeft(i) - innerPaddingX; + bounds.left = layout.getLineLeft(i) -innerPaddingX; bounds.right = layout.getLineRight(i) + innerPaddingX; bounds.top = previousBottom; bounds.bottom = layout.getLineBottom(i); - previousBottom = bounds.bottom; c.drawRoundRect(bounds, cornerRadius, cornerRadius, paint); } } - final int edgeType = mEdgeType; - if (edgeType == CaptionStyle.EDGE_TYPE_OUTLINE) { - paint.setColor(mEdgeColor); - paint.setStyle(Style.FILL_AND_STROKE); - paint.setStrokeJoin(Join.ROUND); - paint.setStrokeWidth(mOutlineWidth); + if (mEdgeType == CaptionStyle.EDGE_TYPE_OUTLINE) { + textPaint.setStrokeJoin(Join.ROUND); + textPaint.setStrokeWidth(mOutlineWidth); + textPaint.setColor(mEdgeColor); + textPaint.setStyle(Style.FILL_AND_STROKE); for (int i = 0; i < lineCount; i++) { layout.drawText(c, i, i); } + } else if (mEdgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) { + textPaint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mEdgeColor); } - if (edgeType == CaptionStyle.EDGE_TYPE_DROP_SHADOW) { - paint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mEdgeColor); - } - - paint.setColor(mForegroundColor); - paint.setStyle(Style.FILL); + textPaint.setColor(mForegroundColor); + textPaint.setStyle(Style.FILL); for (int i = 0; i < lineCount; i++) { layout.drawText(c, i, i); } + textPaint.setShadowLayer(0, 0, 0, 0); c.restoreToCount(saveCount); } } diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index c8ace44c2c51..a7c5b20e027b 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -553,6 +553,11 @@ public class BitmapFactory { * @return The decoded bitmap, or null if the image data could not be * decoded, or, if opts is non-null, if opts requested only the * size be returned (in opts.outWidth and opts.outHeight) + * + * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT}, + * if {@link InputStream#markSupported is.markSupported()} returns true, + * <code>is.mark(1024)</code> would be called. As of + * {@link android.os.Build.VERSION_CODES#KITKAT}, this is no longer the case.</p> */ public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) { // we don't throw in this case, thus allowing the caller to only check diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java index 3524b25533f1..3a99977df758 100644 --- a/graphics/java/android/graphics/BitmapRegionDecoder.java +++ b/graphics/java/android/graphics/BitmapRegionDecoder.java @@ -104,6 +104,11 @@ public final class BitmapRegionDecoder { * allowing sharing may degrade the decoding speed. * @return BitmapRegionDecoder, or null if the image data could not be decoded. * @throws IOException if the image format is not supported or can not be decoded. + * + * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT}, + * if {@link InputStream#markSupported is.markSupported()} returns true, + * <code>is.mark(1024)</code> would be called. As of + * {@link android.os.Build.VERSION_CODES#KITKAT}, this is no longer the case.</p> */ public static BitmapRegionDecoder newInstance(InputStream is, boolean isShareable) throws IOException { diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h index 5e574a6cbddf..25d4c5ea05c3 100644 --- a/libs/hwui/Extensions.h +++ b/libs/hwui/Extensions.h @@ -41,7 +41,7 @@ public: inline bool has1BitStencil() const { return mHas1BitStencil; } inline bool has4BitStencil() const { return mHas4BitStencil; } inline bool hasNvSystemTime() const { return mHasNvSystemTime; } - + inline bool hasUnpackRowLength() const { return mVersionMajor >= 3; } inline bool hasPixelBufferObjects() const { return mVersionMajor >= 3; } inline bool hasOcclusionQueries() const { return mVersionMajor >= 3; } inline bool hasFloatTextures() const { return mVersionMajor >= 3; } diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index a63cac663515..ed0a79aac56a 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -240,20 +240,20 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege switch (bitmap->getConfig()) { case SkBitmap::kA8_Config: glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height, - GL_UNSIGNED_BYTE, bitmap->getPixels()); + uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), + texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels()); texture->blend = true; break; case SkBitmap::kRGB_565_Config: glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); - uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), texture->height, - GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels()); + uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), + texture->width, texture->height, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels()); texture->blend = false; break; case SkBitmap::kARGB_8888_Config: glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); - uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, - GL_UNSIGNED_BYTE, bitmap->getPixels()); + uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), + texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels()); // Do this after calling getPixels() to make sure Skia's deferred // decoding happened texture->blend = !bitmap->isOpaque(); @@ -293,17 +293,28 @@ void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap, SkCanvas canvas(rgbaBitmap); canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL); - uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), height, + uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), width, height, GL_UNSIGNED_BYTE, rgbaBitmap.getPixels()); } -void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height, - GLenum type, const GLvoid * data) { +void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei stride, + GLsizei width, GLsizei height, GLenum type, const GLvoid * data) { + // TODO: With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer + // if the stride doesn't match the width + const bool useStride = stride != width && Extensions::getInstance().hasUnpackRowLength(); + if (useStride) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); + } + if (resize) { glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data); } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data); } + + if (useStride) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } } }; // namespace uirenderer diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 80bb22e27f09..57fc19a16f49 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -125,8 +125,8 @@ private: void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false); void uploadLoFiTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height); - void uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height, - GLenum type, const GLvoid * data); + void uploadToTexture(bool resize, GLenum format, GLsizei stride, + GLsizei width, GLsizei height, GLenum type, const GLvoid * data); void init(); diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp index cbed3e42c79e..d5f38b55a38a 100644 --- a/libs/hwui/font/CacheTexture.cpp +++ b/libs/hwui/font/CacheTexture.cpp @@ -119,7 +119,7 @@ CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint3 // OpenGL ES 3.0+ lets us specify the row length for unpack operations such // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture. // With OpenGL ES 2.0 we have to upload entire stripes instead. - mHasES3 = Extensions::getInstance().getMajorGlVersion() >= 3; + mHasUnpackRowLength = Extensions::getInstance().hasUnpackRowLength(); } CacheTexture::~CacheTexture() { @@ -206,21 +206,21 @@ void CacheTexture::allocateTexture() { bool CacheTexture::upload() { const Rect& dirtyRect = mDirtyRect; - uint32_t x = mHasES3 ? dirtyRect.left : 0; + uint32_t x = mHasUnpackRowLength ? dirtyRect.left : 0; uint32_t y = dirtyRect.top; - uint32_t width = mHasES3 ? dirtyRect.getWidth() : mWidth; + uint32_t width = mHasUnpackRowLength ? dirtyRect.getWidth() : mWidth; uint32_t height = dirtyRect.getHeight(); // The unpack row length only needs to be specified when a new // texture is bound - if (mHasES3) { + if (mHasUnpackRowLength) { glPixelStorei(GL_UNPACK_ROW_LENGTH, mWidth); } mTexture->upload(x, y, width, height); setDirty(false); - return mHasES3; + return mHasUnpackRowLength; } void CacheTexture::setDirty(bool dirty) { diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h index 028b61105c3e..61b38f8f6b19 100644 --- a/libs/hwui/font/CacheTexture.h +++ b/libs/hwui/font/CacheTexture.h @@ -190,7 +190,7 @@ private: uint32_t mMaxQuadCount; Caches& mCaches; CacheBlock* mCacheBlocks; - bool mHasES3; + bool mHasUnpackRowLength; Rect mDirtyRect; }; diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java index edde68d7ee16..4dec0819d8dd 100644 --- a/media/java/android/media/WebVttRenderer.java +++ b/media/java/android/media/WebVttRenderer.java @@ -17,6 +17,7 @@ package android.media; import android.content.Context; +import android.text.Layout.Alignment; import android.text.SpannableStringBuilder; import android.util.ArrayMap; import android.util.AttributeSet; @@ -1583,6 +1584,7 @@ class WebVttRenderingWidget extends ViewGroup implements SubtitleTrack.Rendering } final CueLayout cueBox = new CueLayout(getContext(), cue, mCaptionStyle, mFontSize); + mRegionCueBoxes.add(cueBox); addView(cueBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); if (getChildCount() > mRegion.mLines) { @@ -1696,12 +1698,27 @@ class WebVttRenderingWidget extends ViewGroup implements SubtitleTrack.Rendering removeAllViews(); + final int cueAlignment = resolveCueAlignment(getLayoutDirection(), mCue.mAlignment); + final Alignment alignment; + switch (cueAlignment) { + case TextTrackCue.ALIGNMENT_LEFT: + alignment = Alignment.ALIGN_LEFT; + break; + case TextTrackCue.ALIGNMENT_RIGHT: + alignment = Alignment.ALIGN_RIGHT; + break; + case TextTrackCue.ALIGNMENT_MIDDLE: + default: + alignment = Alignment.ALIGN_CENTER; + } + final CaptionStyle captionStyle = mCaptionStyle; final float fontSize = mFontSize; final TextTrackCueSpan[][] lines = mCue.mLines; final int lineCount = lines.length; for (int i = 0; i < lineCount; i++) { final SpanLayout lineBox = new SpanLayout(getContext(), lines[i]); + lineBox.setAlignment(alignment); lineBox.setCaptionStyle(captionStyle, fontSize); addView(lineBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 8d55ec4619da..ca9bea43aab1 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -295,14 +295,14 @@ public class DocumentsActivity extends Activity { .query(RecentsProvider.buildResume(packageName), null, null, null, null); try { if (cursor.moveToFirst()) { + mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0; final byte[] rawStack = cursor.getBlob( cursor.getColumnIndex(ResumeColumns.STACK)); DurableUtils.readFromArray(rawStack, mState.stack); mRestoredStack = true; - mExternal = cursor.getInt(cursor.getColumnIndex(ResumeColumns.EXTERNAL)) != 0; } } catch (IOException e) { - Log.w(TAG, "Failed to resume", e); + Log.w(TAG, "Failed to resume: " + e); } finally { IoUtils.closeQuietly(cursor); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java index 670d5c0a076e..c975382b8bae 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java @@ -48,6 +48,7 @@ import android.widget.TextView; import com.android.documentsui.DocumentsActivity.State; import com.android.documentsui.RecentsProvider.RecentColumns; import com.android.documentsui.model.DocumentStack; +import com.android.documentsui.model.DurableUtils; import com.android.documentsui.model.RootInfo; import com.google.android.collect.Lists; @@ -160,7 +161,7 @@ public class RecentsCreateFragment extends Fragment { cursor.getColumnIndex(RecentColumns.STACK)); try { final DocumentStack stack = new DocumentStack(); - stack.read(new DataInputStream(new ByteArrayInputStream(rawStack))); + DurableUtils.readFromArray(rawStack, stack); // Only update root here to avoid spinning up all // providers; we update the stack during the actual diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java b/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java index 214fb144e8c9..2a29cbc23d0c 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/DurableUtils.java @@ -36,6 +36,7 @@ public class DurableUtils { } public static <D extends Durable> D readFromArray(byte[] data, D d) throws IOException { + if (data == null) throw new IOException("Missing data"); final ByteArrayInputStream in = new ByteArrayInputStream(data); d.reset(); try { diff --git a/packages/Keyguard/res/layout-land/keyguard_status_area.xml b/packages/Keyguard/res/layout-land/keyguard_status_area.xml index 51ee740befa1..d450c5c6e83c 100644 --- a/packages/Keyguard/res/layout-land/keyguard_status_area.xml +++ b/packages/Keyguard/res/layout-land/keyguard_status_area.xml @@ -37,6 +37,7 @@ android:ellipsize="marquee" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="@dimen/kg_status_date_font_size" + android:textAllCaps="@bool/kg_use_all_caps" /> <TextView @@ -51,6 +52,7 @@ android:textAppearance="?android:attr/textAppearance" android:textSize="@dimen/kg_status_line_font_size" android:drawablePadding="4dip" + android:textAllCaps="@bool/kg_use_all_caps" /> </LinearLayout>
\ No newline at end of file diff --git a/packages/Keyguard/res/layout-port/keyguard_status_area.xml b/packages/Keyguard/res/layout-port/keyguard_status_area.xml index d274457ce227..af0d2e8f0304 100644 --- a/packages/Keyguard/res/layout-port/keyguard_status_area.xml +++ b/packages/Keyguard/res/layout-port/keyguard_status_area.xml @@ -41,6 +41,7 @@ android:ellipsize="marquee" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="@dimen/kg_status_date_font_size" + android:textAllCaps="@bool/kg_use_all_caps" /> <TextView @@ -53,6 +54,7 @@ android:textAppearance="?android:attr/textAppearance" android:textSize="@dimen/kg_status_line_font_size" android:drawablePadding="4dip" + android:textAllCaps="@bool/kg_use_all_caps" /> </LinearLayout> diff --git a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml index de673ec08873..313fe9fc48c1 100644 --- a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml +++ b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml @@ -36,7 +36,8 @@ android:ellipsize="marquee" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="@dimen/kg_status_line_font_size" - android:textColor="?android:attr/textColorSecondary"/> + android:textColor="?android:attr/textColorSecondary" + android:textAllCaps="@bool/kg_use_all_caps" /> <LinearLayout android:layout_width="match_parent" @@ -58,7 +59,8 @@ android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="@dimen/kg_status_line_font_size" android:textColor="?android:attr/textColorSecondary" - android:drawablePadding="8dip" /> + android:drawablePadding="8dip" + android:textAllCaps="@bool/kg_use_all_caps" /> <Button android:id="@+id/forgot_password_button" android:layout_width="0dip" @@ -70,7 +72,8 @@ android:textColor="?android:attr/textColorSecondary" android:textAppearance="?android:attr/textAppearanceMedium" android:drawablePadding="8dip" - android:visibility="gone"/> + android:visibility="gone" + android:textAllCaps="@bool/kg_use_all_caps" /> </LinearLayout> </com.android.keyguard.EmergencyCarrierArea> diff --git a/packages/Keyguard/res/values/bools.xml b/packages/Keyguard/res/values/bools.xml index a9f69e5f29e3..5e842d780864 100644 --- a/packages/Keyguard/res/values/bools.xml +++ b/packages/Keyguard/res/values/bools.xml @@ -19,4 +19,5 @@ <bool name="kg_center_small_widgets_vertically">false</bool> <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool> <bool name="kg_show_ime_at_screen_on">true</bool> + <bool name="kg_use_all_caps">true</bool> </resources> diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml index 5cf05f8ed9fb..ba6685aadd45 100644 --- a/packages/Keyguard/res/values/strings.xml +++ b/packages/Keyguard/res/values/strings.xml @@ -149,6 +149,14 @@ <!-- Shown on transport control of lockscreen. Pressing button pauses playback --> <string name="keyguard_accessibility_transport_stop_description">Stop button</string> + <!-- Accessibility description for when the device prompts the user to dismiss keyguard + in order to complete an action. This will be followed by a message about the current + security option (e.g. "Pattern unlock."). [CHAR LIMIT=NONE] --> + <string name="keyguard_accessibility_show_bouncer">Unlock to continue</string> + + <!-- Accessibility description for when the bouncer prompt is dismissed. [CHAR LIMIT=NONE] --> + <string name="keyguard_accessibility_hide_bouncer">Launch canceled</string> + <!-- Password keyboard strings. Used by LockScreen and Settings --><skip /> <!-- Label for "switch to symbols" key. Must be short to fit on key! --> <string name="password_keyboard_label_symbol_key">\?123</string> diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java index 9f0a042f040b..03b09b131524 100644 --- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java +++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java @@ -72,12 +72,7 @@ public class CarrierText extends TextView { } protected void updateCarrierText(State simState, CharSequence plmn, CharSequence spn) { - CharSequence text = getCarrierTextForSimState(simState, plmn, spn); - if (KeyguardViewManager.USE_UPPER_CASE) { - setText(text != null ? text.toString().toUpperCase() : null); - } else { - setText(text); - } + setText(getCarrierTextForSimState(simState, plmn, spn)); } @Override diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java index 8cdcb7a36b37..fd5661366239 100644 --- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java +++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java @@ -127,8 +127,7 @@ public class EmergencyButton extends Button { enabled = mLockPatternUtils.isSecure(); } } - mLockPatternUtils.updateEmergencyCallButtonState(this, phoneState, enabled, - KeyguardViewManager.USE_UPPER_CASE, false); + mLockPatternUtils.updateEmergencyCallButtonState(this, phoneState, enabled, false); } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index aa4371120215..a9e9d3aaa6da 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -24,7 +24,6 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AlertDialog; -import android.app.PendingIntent; import android.app.SearchManager; import android.app.admin.DevicePolicyManager; import android.appwidget.AppWidgetHost; @@ -41,7 +40,6 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.media.RemoteControlClient; -import android.os.Bundle; import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; @@ -49,11 +47,9 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; -import android.telephony.TelephonyManager; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -206,6 +202,13 @@ public class KeyguardHostView extends KeyguardViewBase { } } + public void announceCurrentSecurityMethod() { + View v = (View) getSecurityView(mCurrentSecuritySelection); + if (v != null) { + v.announceForAccessibility(v.getContentDescription()); + } + } + private void getInitialTransportState() { DisplayClientState dcs = KeyguardUpdateMonitor.getInstance(mContext) .getCachedDisplayClientState(); @@ -1663,4 +1666,8 @@ public class KeyguardHostView extends KeyguardViewBase { mAppWidgetContainer.handleExternalCameraEvent(event); } + public void launchCamera() { + mActivityLauncher.launchCamera(getHandler(), null); + } + } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java index 77006c5fef83..d7c5fe2f0c16 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java @@ -137,6 +137,10 @@ public class KeyguardService extends Service { checkPermission(); mKeyguardViewMediator.dispatch(event); } + public void launchCamera() { + checkPermission(); + mKeyguardViewMediator.launchCamera(); + } }; } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java index 29f76f309420..0289a1f4d1d2 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java @@ -116,7 +116,7 @@ public class KeyguardStatusView extends GridLayout { // Update Alarm status String nextAlarm = mLockPatternUtils.getNextAlarm(); if (!TextUtils.isEmpty(nextAlarm)) { - maybeSetUpperCaseText(mAlarmStatusView, nextAlarm); + mAlarmStatusView.setText(nextAlarm); mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0); mAlarmStatusView.setVisibility(View.VISIBLE); } else { @@ -125,7 +125,7 @@ public class KeyguardStatusView extends GridLayout { } void refreshDate() { - maybeSetUpperCaseText(mDateView, mDateFormat.format(new Date())); + mDateView.setText(mDateFormat.format(new Date())); } @Override @@ -144,11 +144,4 @@ public class KeyguardStatusView extends GridLayout { return LockPatternUtils.ID_DEFAULT_STATUS_WIDGET; } - private void maybeSetUpperCaseText(TextView textView, CharSequence text) { - if (KeyguardViewManager.USE_UPPER_CASE) { - textView.setText(text != null ? text.toString().toUpperCase() : null); - } else { - textView.setText(text); - } - } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java index 177e0f836151..a0e44d75247c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java @@ -506,4 +506,10 @@ public class KeyguardViewManager { mKeyguardView.dispatch(event); } } + + public void launchCamera() { + if (mKeyguardView != null) { + mKeyguardView.launchCamera(); + } + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java index 478096cc0acb..0606d838d915 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java @@ -122,6 +122,7 @@ public class KeyguardViewMediator { private static final int KEYGUARD_TIMEOUT = 13; private static final int SHOW_ASSISTANT = 14; private static final int DISPATCH_EVENT = 15; + private static final int LAUNCH_CAMERA = 16; /** * The default amount of time we stay awake (used for all key input) @@ -1071,6 +1072,9 @@ public class KeyguardViewMediator { case DISPATCH_EVENT: handleDispatchEvent((MotionEvent) msg.obj); break; + case LAUNCH_CAMERA: + handleLaunchCamera(); + break; } } }; @@ -1107,6 +1111,10 @@ public class KeyguardViewMediator { sendUserPresentBroadcast(); } + protected void handleLaunchCamera() { + mKeyguardViewManager.launchCamera(); + } + protected void handleDispatchEvent(MotionEvent event) { mKeyguardViewManager.dispatch(event); } @@ -1341,4 +1349,9 @@ public class KeyguardViewMediator { Message msg = mHandler.obtainMessage(DISPATCH_EVENT, event); mHandler.sendMessage(msg); } + + public void launchCamera() { + Message msg = mHandler.obtainMessage(LAUNCH_CAMERA); + mHandler.sendMessage(msg); + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java index d9f947191e42..d1862cd52f1c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java @@ -87,6 +87,11 @@ public class KeyguardViewStateManager implements } public void showBouncer(boolean show) { + CharSequence what = mKeyguardHostView.getContext().getResources().getText( + show ? R.string.keyguard_accessibility_show_bouncer + : R.string.keyguard_accessibility_hide_bouncer); + mKeyguardHostView.announceForAccessibility(what); + mKeyguardHostView.announceCurrentSecurityMethod(); mChallengeLayout.showBouncer(); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java index f7dc0589c2ca..f8857aba3bb4 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java @@ -90,6 +90,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit // Background worker thread: used here for persistence, also made available to widget frames private final HandlerThread mBackgroundWorkerThread; private final Handler mBackgroundWorkerHandler; + private boolean mCameraEventInProgress; public KeyguardWidgetPager(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -941,14 +942,18 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit beginCameraEvent(); int cameraPage = getPageCount() - 1; boolean endWarp = false; - if (isCameraPage(cameraPage)) { + if (isCameraPage(cameraPage) || mCameraEventInProgress) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: + // Once we start dispatching camera events, we must continue to do so + // to keep event dispatch happy. + mCameraEventInProgress = true; userActivity(); startWarp(cameraPage); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + mCameraEventInProgress = false; endWarp = true; break; } diff --git a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml index 765b274ab79b..aa7256bfaf33 100644 --- a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml +++ b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml @@ -153,6 +153,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.DeadZone @@ -297,6 +298,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.DeadZone diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml index 9592b18cacda..b9ad7992bb2d 100644 --- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml +++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml @@ -149,6 +149,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.DeadZone @@ -290,6 +291,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.DeadZone diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml index 11cbbc787c33..aa365aedcfb1 100644 --- a/packages/SystemUI/res/layout/navigation_bar.xml +++ b/packages/SystemUI/res/layout/navigation_bar.xml @@ -157,6 +157,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <com.android.systemui.statusbar.policy.KeyButtonView @@ -167,6 +168,7 @@ android:src="@drawable/ic_sysbar_camera" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_camera_button" /> </FrameLayout> @@ -312,6 +314,7 @@ android:src="@drawable/search_light" android:scaleType="center" android:visibility="gone" + android:contentDescription="@string/accessibility_search_light" /> <!-- No camera button in landscape mode --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index eb425e66c92f..58865ab962bb 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -192,6 +192,10 @@ <string name="accessibility_menu">Menu</string> <!-- Content description of the recents button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_recent">Recent apps</string> + <!-- Content description of the search button for accessibility. [CHAR LIMIT=NONE] --> + <string name="accessibility_search_light">Search</string> + <!-- Content description of the camera button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_camera_button">Camera</string> <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_ime_switch_button">Switch input method button.</string> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java index 3a5524d3117e..3a8275322f18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java @@ -50,8 +50,7 @@ public class DelegateViewHelper { } public boolean onInterceptTouchEvent(MotionEvent event) { - if (mSourceView == null || mDelegateView == null || mDisabled - || mBar.shouldDisableNavbarGestures()) { + if (mSourceView == null || mDelegateView == null || mBar.shouldDisableNavbarGestures()) { return false; } @@ -73,7 +72,7 @@ public class DelegateViewHelper { return false; } - if (!mPanelShowing && action == MotionEvent.ACTION_MOVE) { + if (!mDisabled && !mPanelShowing && action == MotionEvent.ACTION_MOVE) { final int historySize = event.getHistorySize(); for (int k = 0; k < historySize + 1; k++) { float x = k < historySize ? event.getHistoricalX(k) : event.getX(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java index a6e234777775..1221a557a314 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java @@ -103,4 +103,30 @@ public class KeyguardTouchDelegate { return false; } + public void showAssistant() { + if (mService != null) { + try { + mService.showAssistant(); + } catch (RemoteException e) { + // What to do? + Log.e(TAG, "RemoteException launching assistant!", e); + } + } else { + Log.w(TAG, "dispatch(event): NO SERVICE!"); + } + } + + public void launchCamera() { + if (mService != null) { + try { + mService.launchCamera(); + } catch (RemoteException e) { + // What to do? + Log.e(TAG, "RemoteException launching camera!", e); + } + } else { + Log.w(TAG, "dispatch(event): NO SERVICE!"); + } + } + } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 24e27b1f2420..596fac601398 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -37,8 +37,10 @@ import android.view.Display; import android.view.MotionEvent; import android.view.Surface; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.accessibility.AccessibilityManager; import android.widget.ImageView; import android.widget.LinearLayout; @@ -86,7 +88,7 @@ public class NavigationBarView extends LinearLayout { // used to disable the camera icon in navbar when disabled by DPM private boolean mCameraDisabledByDpm; - KeyguardTouchDelegate mTouchDelegate; + KeyguardTouchDelegate mKeyguardTouchDelegate; private final OnTouchListener mCameraTouchListener = new OnTouchListener() { @Override @@ -110,7 +112,7 @@ public class NavigationBarView extends LinearLayout { } break; } - return mTouchDelegate.dispatch(event); + return mKeyguardTouchDelegate.dispatch(event); } }; @@ -153,7 +155,7 @@ public class NavigationBarView extends LinearLayout { mBarTransitions = new NavigationBarTransitions(this); - mTouchDelegate = new KeyguardTouchDelegate(mContext); + mKeyguardTouchDelegate = new KeyguardTouchDelegate(mContext); mCameraDisabledByDpm = isCameraDisabledByDpm(); watchForDevicePolicyChanges(); @@ -339,7 +341,7 @@ public class NavigationBarView extends LinearLayout { final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId); final boolean disabledBecauseKeyguardSecure = (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0 - && mTouchDelegate.isSecure(); + && mKeyguardTouchDelegate.isSecure(); return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure; } catch (RemoteException e) { Log.e(TAG, "Can't get userId", e); @@ -389,12 +391,44 @@ public class NavigationBarView extends LinearLayout { mCurrentView = mRotatedViews[Surface.ROTATION_0]; - // Add a touch handler for camera icon for all view orientations. - for (int i = 0; i < mRotatedViews.length; i++) { - View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button); - if (cameraButton != null) { - cameraButton.setOnTouchListener(mCameraTouchListener); + + final AccessibilityManager accessibilityManager = + (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (accessibilityManager.isEnabled()) { + // In accessibility mode, we add a simple click handler since swipe is tough to + // trigger near screen edges. + View camera = getCameraButton(); + View searchLight = getSearchLight(); + if (camera != null || searchLight != null) { + OnClickListener listener = new OnClickListener() { + @Override + public void onClick(View v) { + launchForAccessibilityClick(v); + } + }; + if (camera != null) { + camera.setOnClickListener(listener); + } + if (searchLight != null) { + searchLight.setOnClickListener(listener); + } } + } else { + // Add a touch handler for camera icon for all view orientations. + for (int i = 0; i < mRotatedViews.length; i++) { + View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button); + if (cameraButton != null) { + cameraButton.setOnTouchListener(mCameraTouchListener); + } + } + } + } + + protected void launchForAccessibilityClick(View v) { + if (v == getCameraButton()) { + mKeyguardTouchDelegate.launchCamera(); + } else if (v == getSearchLight()) { + mKeyguardTouchDelegate.showAssistant(); } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java index b27584da6dc2..5e299ee9a25b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java @@ -192,6 +192,10 @@ public class KeyguardServiceWrapper implements IKeyguardService { // Not used by PhoneWindowManager. See code in {@link NavigationBarView} } + public void launchCamera() { + // Not used by PhoneWindowManager. See code in {@link NavigationBarView} + } + @Override public IBinder asBinder() { return mService.asBinder(); |