Program: 157533
Project: 157533
Buggy source:
private void onBufferDraw(){
  if (mBuffer == null || mKeyboardChanged) {
    if (mBuffer == null || mKeyboardChanged && (mBuffer.getWidth() != getWidth() || mBuffer.getHeight() != getHeight())) {
      final int width=Math.max(1,getWidth());
      final int height=Math.max(1,getHeight());
      mBuffer=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
      mCanvas=new Canvas(mBuffer);
    }
    invalidateAllKeys();
    mKeyboardChanged=false;
  }
  final Canvas canvas=mCanvas;
  canvas.clipRect(mDirtyRect,Op.REPLACE);
  if (mKeyboard == null)   return;
  final Paint paint=mPaint;
  final Drawable keyBackground=mKeyBackground;
  final Rect clipRegion=mClipRegion;
  final Rect padding=mPadding;
  final int kbdPaddingLeft=getPaddingLeft();
  final int kbdPaddingTop=getPaddingTop();
  final Key[] keys=mKeys;
  final Key invalidKey=mInvalidatedKey;
  paint.setColor(mKeyTextColor);
  boolean drawSingleKey=false;
  if (invalidKey != null && canvas.getClipBounds(clipRegion)) {
    if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left && invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top && invalidKey.x + invalidKey.width + kbdPaddingLeft+ 1 >= clipRegion.right && invalidKey.y + invalidKey.height + kbdPaddingTop+ 1 >= clipRegion.bottom) {
      drawSingleKey=true;
    }
  }
  canvas.drawColor(0x00000000,PorterDuff.Mode.CLEAR);
  final int keyCount=keys.length;
  for (int i=0; i < keyCount; i++) {
    final Key key=keys[i];
    if (drawSingleKey && invalidKey != key) {
      continue;
    }
    int[] drawableState=key.getCurrentDrawableState();
    keyBackground.setState(drawableState);
    String label=key.label == null ? null : adjustCase(key.label).toString();
    final Rect bounds=keyBackground.getBounds();
    if (key.width != bounds.right || key.height != bounds.bottom) {
      keyBackground.setBounds(0,0,key.width,key.height);
    }
    canvas.translate(key.x + kbdPaddingLeft,key.y + kbdPaddingTop);
    keyBackground.draw(canvas);
    boolean shouldDrawIcon=true;
    if (label != null) {
      final int labelSize;
      if (label.length() > 1 && key.codes.length < 2) {
        labelSize=mLabelTextSize;
        paint.setTypeface(Typeface.DEFAULT_BOLD);
      }
 else {
        labelSize=mKeyTextSize;
        paint.setTypeface(mKeyTextStyle);
      }
      paint.setTextSize(labelSize);
      Integer labelHeightValue=mTextHeightCache.get(labelSize);
      final int labelHeight;
      if (labelHeightValue != null) {
        labelHeight=labelHeightValue;
      }
 else {
        Rect textBounds=new Rect();
        paint.getTextBounds(KEY_LABEL_HEIGHT_REFERENCE_CHAR,0,1,textBounds);
        labelHeight=textBounds.height();
        mTextHeightCache.put(labelSize,labelHeight);
      }
      paint.setShadowLayer(mShadowRadius,0,0,mShadowColor);
      final int centerX=(key.width + padding.left - padding.right) / 2;
      final int centerY=(key.height + padding.top - padding.bottom) / 2;
      final float baseline=centerY + labelHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR;
      canvas.drawText(label,centerX,baseline,paint);
      paint.setShadowLayer(0,0,0,0);
      shouldDrawIcon=shouldDrawLabelAndIcon(key);
    }
    if (key.icon != null && shouldDrawIcon) {
      final int drawableWidth;
      final int drawableHeight;
      final int drawableX;
      final int drawableY;
      if (shouldDrawIconFully(key)) {
        drawableWidth=key.width;
        drawableHeight=key.height;
        drawableX=0;
        drawableY=NUMBER_HINT_VERTICAL_ADJUSTMENT_PIXEL;
      }
 else {
        drawableWidth=key.icon.getIntrinsicWidth();
        drawableHeight=key.icon.getIntrinsicHeight();
        drawableX=(key.width + padding.left - padding.right - drawableWidth) / 2;
        drawableY=(key.height + padding.top - padding.bottom - drawableHeight) / 2;
      }
      canvas.translate(drawableX,drawableY);
      key.icon.setBounds(0,0,drawableWidth,drawableHeight);
      key.icon.draw(canvas);
      canvas.translate(-drawableX,-drawableY);
    }
    canvas.translate(-key.x - kbdPaddingLeft,-key.y - kbdPaddingTop);
  }
  mInvalidatedKey=null;
  if (mMiniKeyboard != null) {
    paint.setColor((int)(mBackgroundDimAmount * 0xFF) << 24);
    canvas.drawRect(0,0,getWidth(),getHeight(),paint);
  }
  if (AnySoftKeyboardConfiguration.DEBUG) {
    if (mShowTouchPoints) {
      for (      PointerTracker tracker : mPointerTrackers) {
        int startX=tracker.getStartX();
        int startY=tracker.getStartY();
        int lastX=tracker.getLastX();
        int lastY=tracker.getLastY();
        paint.setAlpha(128);
        paint.setColor(0xFFFF0000);
        canvas.drawCircle(startX,startY,3,paint);
        canvas.drawLine(startX,startY,lastX,lastY,paint);
        paint.setColor(0xFF0000FF);
        canvas.drawCircle(lastX,lastY,3,paint);
        paint.setColor(0xFF00FF00);
        canvas.drawCircle((startX + lastX) / 2,(startY + lastY) / 2,2,paint);
      }
    }
  }
  mDrawPending=false;
  mDirtyRect.setEmpty();
}

Fixed version (ground truth):
private void onBufferDraw(){
  if (mBuffer == null || mKeyboardChanged) {
    if (mBuffer == null || mKeyboardChanged && (mBuffer.getWidth() != getWidth() || mBuffer.getHeight() != getHeight())) {
      final int width=Math.max(1,getWidth());
      final int height=Math.max(1,getHeight());
      mBuffer=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
      mCanvas=new Canvas(mBuffer);
    }
    invalidateAllKeys();
    mKeyboardChanged=false;
  }
  final Canvas canvas=mCanvas;
  canvas.clipRect(mDirtyRect,Op.REPLACE);
  if (mKeyboard == null)   return;
  final Paint paint=mPaint;
  final Drawable keyBackground=mKeyBackground;
  final Rect clipRegion=mClipRegion;
  final Rect padding=mPadding;
  final int kbdPaddingLeft=getPaddingLeft();
  final int kbdPaddingTop=getPaddingTop();
  final Key[] keys=mKeys;
  final Key invalidKey=mInvalidatedKey;
  paint.setColor(mKeyTextColor);
  boolean drawSingleKey=false;
  if (invalidKey != null && canvas.getClipBounds(clipRegion)) {
    if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left && invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top && invalidKey.x + invalidKey.width + kbdPaddingLeft+ 1 >= clipRegion.right && invalidKey.y + invalidKey.height + kbdPaddingTop+ 1 >= clipRegion.bottom) {
      drawSingleKey=true;
    }
  }
  canvas.drawColor(0x00000000,PorterDuff.Mode.CLEAR);
  final int keyCount=keys.length;
  for (int i=0; i < keyCount; i++) {
    final Key key=keys[i];
    if (drawSingleKey && invalidKey != key) {
      continue;
    }
    int[] drawableState=key.getCurrentDrawableState();
    keyBackground.setState(drawableState);
    String label=key.label == null ? null : adjustCase(key.label).toString();
    final Rect bounds=keyBackground.getBounds();
    if (key.width != bounds.right || key.height != bounds.bottom) {
      keyBackground.setBounds(0,0,key.width,key.height);
    }
    canvas.translate(key.x + kbdPaddingLeft,key.y + kbdPaddingTop);
    keyBackground.draw(canvas);
    boolean shouldDrawIcon=true;
    if (label != null) {
      final int labelSize;
      if (label.length() > 1 && key.codes.length < 2) {
        labelSize=mLabelTextSize;
        paint.setTypeface(Typeface.DEFAULT_BOLD);
      }
 else {
        labelSize=mKeyTextSize;
        paint.setTypeface(mKeyTextStyle);
      }
      paint.setTextSize(labelSize);
      Integer labelHeightValue=mTextHeightCache.get(labelSize);
      final int labelHeight;
      if (labelHeightValue != null) {
        labelHeight=labelHeightValue;
      }
 else {
        Rect textBounds=new Rect();
        paint.getTextBounds(KEY_LABEL_HEIGHT_REFERENCE_CHAR,0,1,textBounds);
        labelHeight=textBounds.height();
        mTextHeightCache.put(labelSize,labelHeight);
      }
      paint.setShadowLayer(mShadowRadius,0,0,mShadowColor);
      final float centerX=(key.width + padding.left - padding.right) / 2;
      final float centerY=padding.top + ((key.height - -padding.bottom - padding.top) / 2);
      float textX=centerX;
      float textY=centerY - (labelHeight / 2) - paint.descent();
      canvas.translate(textX,textY);
      TextPaint labelPaint=new TextPaint(paint);
      StaticLayout labelText=new StaticLayout(label,labelPaint,key.width,Alignment.ALIGN_NORMAL,1.0f,1.0f,false);
      labelText.draw(canvas);
      canvas.translate(-textX,-textY);
      paint.setShadowLayer(0,0,0,0);
      shouldDrawIcon=shouldDrawLabelAndIcon(key);
    }
    if (key.icon != null && shouldDrawIcon) {
      final int drawableWidth;
      final int drawableHeight;
      final int drawableX;
      final int drawableY;
      if (shouldDrawIconFully(key)) {
        drawableWidth=key.width;
        drawableHeight=key.height;
        drawableX=0;
        drawableY=NUMBER_HINT_VERTICAL_ADJUSTMENT_PIXEL;
      }
 else {
        drawableWidth=key.icon.getIntrinsicWidth();
        drawableHeight=key.icon.getIntrinsicHeight();
        drawableX=(key.width + padding.left - padding.right - drawableWidth) / 2;
        drawableY=(key.height + padding.top - padding.bottom - drawableHeight) / 2;
      }
      canvas.translate(drawableX,drawableY);
      key.icon.setBounds(0,0,drawableWidth,drawableHeight);
      key.icon.draw(canvas);
      canvas.translate(-drawableX,-drawableY);
    }
    canvas.translate(-key.x - kbdPaddingLeft,-key.y - kbdPaddingTop);
  }
  mInvalidatedKey=null;
  if (mMiniKeyboard != null) {
    paint.setColor((int)(mBackgroundDimAmount * 0xFF) << 24);
    canvas.drawRect(0,0,getWidth(),getHeight(),paint);
  }
  if (AnySoftKeyboardConfiguration.DEBUG) {
    if (mShowTouchPoints) {
      for (      PointerTracker tracker : mPointerTrackers) {
        int startX=tracker.getStartX();
        int startY=tracker.getStartY();
        int lastX=tracker.getLastX();
        int lastY=tracker.getLastY();
        paint.setAlpha(128);
        paint.setColor(0xFFFF0000);
        canvas.drawCircle(startX,startY,3,paint);
        canvas.drawLine(startX,startY,lastX,lastY,paint);
        paint.setColor(0xFF0000FF);
        canvas.drawCircle(lastX,lastY,3,paint);
        paint.setColor(0xFF00FF00);
        canvas.drawCircle((startX + lastX) / 2,(startY + lastY) / 2,2,paint);
      }
    }
  }
  mDrawPending=false;
  mDirtyRect.setEmpty();
}