Program: 40727
Project: 40727
Buggy source:
@Override public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
  if (loadPackageParam.packageName.equals(BuildConfig.PACKAGE_NAME)) {
    XposedHelpers.findAndHookMethod(XApp.class.getCanonicalName(),loadPackageParam.classLoader,"String_Node_Str",XC_MethodReplacement.returnConstant(true));
  }
  if (!loadPackageParam.packageName.equals(HANGOUTS_PKG_NAME)) {
    return;
  }
  Object activityThread=XposedHelpers.callStaticMethod(XposedHelpers.findClass(ACTIVITY_THREAD_CLASS,null),ACTIVITY_THREAD_CURRENTACTHREAD);
  final Context systemCtx=(Context)XposedHelpers.callMethod(activityThread,ACTIVITY_THREAD_GETSYSCTX);
  Config.reload(systemCtx);
  if (!Config.modEnabled) {
    return;
  }
  debug("String_Node_Str",false);
  debug(String.format("String_Node_Str",BuildConfig.VERSION_NAME,BuildConfig.VERSION_CODE),false);
  PackageInfo pi=systemCtx.getPackageManager().getPackageInfo(HANGOUTS_PKG_NAME,0);
  debug(String.format("String_Node_Str",pi.versionName,pi.versionCode),false);
  if (pi.versionCode != TESTED_VERSION_INT) {
    log(String.format("String_Node_Str",TESTED_VERSION_STR,TESTED_VERSION_INT));
  }
  XposedHelpers.findAndHookMethod(HANGOUTS_ESAPP_CLASS,loadPackageParam.classLoader,HANGOUTS_ESAPP_ONCREATE,new XC_MethodHook(){
    @Override protected void afterHookedMethod(    MethodHookParam param) throws Throwable {
      debug("String_Node_Str");
      hangoutsCtx=new WeakReference<Context>((Context)param.thisObject);
    }
  }
);
  XposedHelpers.findAndHookMethod(HANGOUTS_PROCESS_MMS_IMG_CLASS,loadPackageParam.classLoader,HANGOUTS_PROCESS_MMS_IMG_METHOD,int.class,int.class,int.class,int.class,Uri.class,new XC_MethodHook(){
    @Override protected void afterHookedMethod(    MethodHookParam param) throws Throwable {
      Config.reload(systemCtx);
      if (!Config.modEnabled || !Config.resizing) {
        return;
      }
      final int maxWidth=(Integer)param.args[1];
      final int maxHeight=(Integer)param.args[2];
      final Uri imgUri=(Uri)param.args[4];
      debug(String.format("String_Node_Str",maxWidth,maxHeight,imgUri,param.args[0],param.args[3]));
      ContentResolver esAppResolver=hangoutsCtx.get().getContentResolver();
      InputStream imgStream=esAppResolver.openInputStream(imgUri);
      BitmapFactory.Options options=new BitmapFactory.Options();
      options.inJustDecodeBounds=true;
      BitmapFactory.decodeStream(imgStream,null,options);
      imgStream.close();
      int srcW=options.outWidth;
      int srcH=options.outHeight;
      debug(String.format("String_Node_Str",srcW,srcH));
      int rotation=0;
      if (Config.rotation) {
        rotation=Config.rotateMode;
        if (rotation == -1) {
          String scratchId=imgUri.getPathSegments().get(1);
          String filePath=(String)XposedHelpers.callStaticMethod(XposedHelpers.findClass(HANGOUTS_ESPROVIDER_CLASS,loadPackageParam.classLoader),HANGOUTS_ESPROVIDER_GET_SCRATCH_FILE,scratchId);
          debug(String.format("String_Node_Str",filePath));
          ExifInterface exif=new ExifInterface(filePath);
switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)) {
case ExifInterface.ORIENTATION_ROTATE_90:
            rotation=90;
          break;
case ExifInterface.ORIENTATION_ROTATE_180:
        rotation=180;
      break;
case ExifInterface.ORIENTATION_ROTATE_270:
    rotation=270;
  break;
default :
rotation=0;
}
}
if (rotation != 0) {
Matrix imgMatrix=new Matrix();
imgMatrix.postRotate(rotation);
RectF imgRect=new RectF();
imgMatrix.mapRect(imgRect,new RectF(0,0,srcW,srcH));
srcW=Math.round(imgRect.width());
srcH=Math.round(imgRect.height());
debug(String.format("String_Node_Str",srcW,srcH,rotation));
}
}
int inSS=1;
while ((srcW / 2 > maxWidth) || (srcH / 2 > maxHeight)) {
srcW/=2;
srcH/=2;
inSS*=2;
}
float scale=((float)(srcW > srcH ? maxWidth : maxHeight)) / (srcW > srcH ? srcW : srcH);
debug(String.format("String_Node_Str",srcW,srcH,inSS,scale));
options.inJustDecodeBounds=false;
options.inDither=false;
options.inSampleSize=inSS;
options.inScaled=false;
options.inPreferredConfig=Bitmap.Config.ARGB_8888;
imgStream=esAppResolver.openInputStream(imgUri);
Bitmap sampled=BitmapFactory.decodeStream(imgStream,null,options);
imgStream.close();
debug(String.format("String_Node_Str",sampled.getWidth(),sampled.getHeight()));
Matrix m=new Matrix();
m.postScale(scale,scale);
m.postRotate(rotation);
Bitmap scaled=Bitmap.createBitmap(sampled,0,0,sampled.getWidth(),sampled.getHeight(),m,true);
sampled.recycle();
debug(String.format("String_Node_Str",scaled.getWidth(),scaled.getHeight()));
ByteArrayOutputStream output=new ByteArrayOutputStream();
scaled.compress(Bitmap.CompressFormat.PNG,0,output);
scaled.recycle();
param.setResult(output.toByteArray());
output.close();
debug("String_Node_Str");
}
}
);
Class<?> ComposeMessageView=XposedHelpers.findClass(HANGOUTS_VIEWS_COMPOSEMSGVIEW,loadPackageParam.classLoader);
XposedHelpers.findAndHookConstructor(ComposeMessageView,Context.class,AttributeSet.class,new XC_MethodHook(){
@Override protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Config.reload((Context)param.args[0]);
if (Config.modEnabled) {
Setting.UiEnterKey enterKey=Setting.UiEnterKey.fromInt(Config.enterKey);
debug(String.format("String_Node_Str",enterKey.name()));
if (enterKey != Setting.UiEnterKey.EMOJI_SELECTOR) {
EditText et=(EditText)XposedHelpers.getObjectField(param.thisObject,HANGOUTS_VIEWS_COMPOSEMSGVIEW_EDITTEXT);
et.setInputType(et.getInputType() ^ InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE);
}
}
}
}
);
XposedHelpers.findAndHookMethod(ComposeMessageView,HANGOUTS_VIEWS_COMEPOSEMSGVIEW_ONEDITORACTION,TextView.class,int.class,KeyEvent.class,new XC_MethodHook(){
@Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
int actionId=(Integer)param.args[1];
if (Config.modEnabled && actionId == EditorInfo.IME_NULL && Config.enterKey == Setting.UiEnterKey.NEWLINE.toInt()) {
param.setResult(false);
}
}
}
);
debug("String_Node_Str",false);
}

Fixed version (ground truth):
@Override public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
  if (loadPackageParam.packageName.equals(BuildConfig.PACKAGE_NAME)) {
    XposedHelpers.findAndHookMethod(XApp.class.getCanonicalName(),loadPackageParam.classLoader,"String_Node_Str",XC_MethodReplacement.returnConstant(true));
  }
  if (!loadPackageParam.packageName.equals(HANGOUTS_PKG_NAME)) {
    return;
  }
  Object activityThread=XposedHelpers.callStaticMethod(XposedHelpers.findClass(ACTIVITY_THREAD_CLASS,null),ACTIVITY_THREAD_CURRENTACTHREAD);
  final Context systemCtx=(Context)XposedHelpers.callMethod(activityThread,ACTIVITY_THREAD_GETSYSCTX);
  Config.reload(systemCtx);
  if (!Config.modEnabled) {
    return;
  }
  debug("String_Node_Str",false);
  debug(String.format("String_Node_Str",BuildConfig.VERSION_NAME,BuildConfig.VERSION_CODE),false);
  PackageInfo pi=systemCtx.getPackageManager().getPackageInfo(HANGOUTS_PKG_NAME,0);
  debug(String.format("String_Node_Str",pi.versionName,pi.versionCode),false);
  if (pi.versionCode != TESTED_VERSION_INT) {
    log(String.format("String_Node_Str",TESTED_VERSION_STR,TESTED_VERSION_INT));
  }
  XposedHelpers.findAndHookMethod(HANGOUTS_ESAPP_CLASS,loadPackageParam.classLoader,HANGOUTS_ESAPP_ONCREATE,new XC_MethodHook(){
    @Override protected void afterHookedMethod(    MethodHookParam param) throws Throwable {
      debug("String_Node_Str");
      hangoutsCtx=new WeakReference<Context>((Context)param.thisObject);
    }
  }
);
  XposedHelpers.findAndHookMethod(HANGOUTS_PROCESS_MMS_IMG_CLASS,loadPackageParam.classLoader,HANGOUTS_PROCESS_MMS_IMG_METHOD,int.class,int.class,int.class,int.class,Uri.class,new XC_MethodHook(){
    @Override protected void afterHookedMethod(    MethodHookParam param) throws Throwable {
      Config.reload(systemCtx);
      if (!Config.modEnabled || !Config.resizing) {
        return;
      }
      final int maxWidth=(Integer)param.args[1];
      final int maxHeight=(Integer)param.args[2];
      final Uri imgUri=(Uri)param.args[4];
      debug(String.format("String_Node_Str",maxWidth,maxHeight,imgUri,param.args[0],param.args[3]));
      ContentResolver esAppResolver=hangoutsCtx.get().getContentResolver();
      InputStream imgStream=esAppResolver.openInputStream(imgUri);
      BitmapFactory.Options options=new BitmapFactory.Options();
      options.inJustDecodeBounds=true;
      BitmapFactory.decodeStream(imgStream,null,options);
      imgStream.close();
      int srcW=options.outWidth;
      int srcH=options.outHeight;
      debug(String.format("String_Node_Str",srcW,srcH));
      int rotation=0;
      if (Config.rotation) {
        rotation=Config.rotateMode;
        if (rotation == -1) {
          String scratchId=imgUri.getPathSegments().get(1);
          String filePath=(String)XposedHelpers.callStaticMethod(XposedHelpers.findClass(HANGOUTS_ESPROVIDER_CLASS,loadPackageParam.classLoader),HANGOUTS_ESPROVIDER_GET_SCRATCH_FILE,scratchId);
          debug(String.format("String_Node_Str",filePath));
          ExifInterface exif=new ExifInterface(filePath);
switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)) {
case ExifInterface.ORIENTATION_ROTATE_90:
            rotation=90;
          break;
case ExifInterface.ORIENTATION_ROTATE_180:
        rotation=180;
      break;
case ExifInterface.ORIENTATION_ROTATE_270:
    rotation=270;
  break;
default :
rotation=0;
}
}
if (rotation != 0) {
Matrix imgMatrix=new Matrix();
imgMatrix.postRotate(rotation);
RectF imgRect=new RectF();
imgMatrix.mapRect(imgRect,new RectF(0,0,srcW,srcH));
srcW=Math.round(imgRect.width());
srcH=Math.round(imgRect.height());
debug(String.format("String_Node_Str",srcW,srcH,rotation));
}
}
int inSS=1;
while ((srcW / 2 > maxWidth) || (srcH / 2 > maxHeight)) {
srcW/=2;
srcH/=2;
inSS*=2;
}
float scale=((float)(srcW > srcH ? maxWidth : maxHeight)) / (srcW > srcH ? srcW : srcH);
debug(String.format("String_Node_Str",srcW,srcH,inSS,scale));
options.inJustDecodeBounds=false;
options.inDither=false;
options.inSampleSize=inSS;
options.inScaled=false;
options.inPreferredConfig=Bitmap.Config.ARGB_8888;
imgStream=esAppResolver.openInputStream(imgUri);
Bitmap sampled=BitmapFactory.decodeStream(imgStream,null,options);
imgStream.close();
debug(String.format("String_Node_Str",sampled.getWidth(),sampled.getHeight()));
Matrix m=new Matrix();
m.postScale(scale,scale);
m.postRotate(rotation);
Bitmap scaled=Bitmap.createBitmap(sampled,0,0,sampled.getWidth(),sampled.getHeight(),m,true);
sampled.recycle();
debug(String.format("String_Node_Str",scaled.getWidth(),scaled.getHeight()));
ByteArrayOutputStream output=new ByteArrayOutputStream();
scaled.compress(Bitmap.CompressFormat.PNG,0,output);
scaled.recycle();
param.setResult(output.toByteArray());
output.close();
debug("String_Node_Str");
}
}
);
Class<?> ComposeMessageView=XposedHelpers.findClass(HANGOUTS_VIEWS_COMPOSEMSGVIEW,loadPackageParam.classLoader);
XposedHelpers.findAndHookConstructor(ComposeMessageView,Context.class,AttributeSet.class,new XC_MethodHook(){
@Override protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Config.reload((Context)param.args[0]);
if (Config.modEnabled) {
Setting.UiEnterKey enterKey=Setting.UiEnterKey.fromInt(Config.enterKey);
debug(String.format("String_Node_Str",enterKey.name()));
if (enterKey != Setting.UiEnterKey.EMOJI_SELECTOR) {
EditText et=(EditText)XposedHelpers.getObjectField(param.thisObject,HANGOUTS_VIEWS_COMPOSEMSGVIEW_EDITTEXT);
int inputType=et.getInputType() ^ InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE;
if (enterKey == Setting.UiEnterKey.SEND) {
inputType^=InputType.TYPE_TEXT_FLAG_MULTI_LINE;
}
et.setInputType(inputType);
}
}
}
}
);
XposedHelpers.findAndHookMethod(ComposeMessageView,HANGOUTS_VIEWS_COMEPOSEMSGVIEW_ONEDITORACTION,TextView.class,int.class,KeyEvent.class,new XC_MethodHook(){
@Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
int actionId=(Integer)param.args[1];
if (Config.modEnabled && actionId == EditorInfo.IME_NULL && Config.enterKey == Setting.UiEnterKey.NEWLINE.toInt()) {
param.setResult(false);
}
}
}
);
debug("String_Node_Str",false);
}