Декомпиляция и обновление Android-приложения до Android M

256
15 августа 2017, 13:25

Добрый день! Имеется старый проект QEMU for Android, который не обновлялся с 2010 года (то есть почти 8 лет). Соответственно, проект не имеет ни Runtime Permissions, ни сертификата второго уровня. Требуется заставить работать это приложение на Android Marshmallow, для начала неплохо было бы внедрить хотя бы Runtime Permissions.

В первую очередь я попробовал декомпилировать проект через Virtuos Ten Studio, чтобы узнать версию используемой Activity (именно эта программа, так как она смогла разобрать и собрать этот проект, после маленькой редакции smali-кода). На выходе получил это в методе onCreate в первой активности, которая стартует (код немного обрезан, так как целиком не влез):

   .method public onCreate(Landroid/os/Bundle;)V
    .locals 11
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;
    .prologue
    const/4 v8, 0x1
    const/4 v9, 0x0
    const-string v10, "Ok"
    const-string v7, "Error"
    .line 178
    const/4 v4, 0x0
    .line 179
    .local v4, "vers":I
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
    .line 180
    invoke-static {v8}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
    move-result-object v0
    .line 192
    .local v0, "Ok":Ljava/lang/Boolean;
    :try_start_0
    invoke-static {}, LlibSDL/jni/libSDLproxy;->libSDLcheckloaded()I
    :try_end_0
    .catch Ljava/lang/Throwable; {:try_start_0 .. :try_end_0} :catch_0
    move-result v4
    .line 202
    :goto_0
    invoke-virtual {v0}, Ljava/lang/Boolean;->booleanValue()Z
    invoke-virtual {v5}, Ljava/lang/Boolean;->booleanValue()Z
    move-result v5
    if-nez v5, :cond_2
    .line 224
    iget-object v5, p0, LlibSDL/jni/libSDL;->sManager:Landroid/hardware/SensorManager;
    invoke-virtual {v5, v8}, Landroid/hardware/SensorManager;->getSensorList(I)Ljava/util/List;
    move-result-object v3
    .line 225
    .local v3, "liste":Ljava/util/List;, "Ljava/util/List<Landroid/hardware/Sensor;>;"
    const/4 v1, 0x0
    .local v1, "a":I
    :goto_2
    invoke-interface {v3}, Ljava/util/List;->size()I
    move-result v5
    if-lt v1, v5, :cond_3
    .line 230
    .end local v1    # "a":I
    .end local v3    # "liste":Ljava/util/List;, "Ljava/util/List<Landroid/hardware/Sensor;>;"
    :cond_2
    invoke-virtual {p0, v9}, LlibSDL/jni/libSDL;->setDefaultKeyMode(I)V
    .line 231
    sget v5, LlibSDL/jni/libSDLconfig;->CONF_DEFAULT_ORIENTATION:I
    invoke-virtual {p0, v5}, LlibSDL/jni/libSDL;->setRequestedOrientation(I)V
    goto :goto_1
    .line 226
    .restart local v1    # "a":I
    .restart local v3    # "liste":Ljava/util/List;, "Ljava/util/List<Landroid/hardware/Sensor;>;"
    :cond_3
    sget-object v6, Ljava/lang/System;->out:Ljava/io/PrintStream;
    new-instance v5, Ljava/lang/StringBuilder;
    const-string v7, "Sensor "
    invoke-direct {v5, v7}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
    invoke-virtual {v5, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
    move-result-object v5
    const-string v7, ": "
    invoke-virtual {v5, v7}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move-result-object v7
    invoke-interface {v3, v1}, Ljava/util/List;->get(I)Ljava/lang/Object;
    move-result-object v5
    check-cast v5, Landroid/hardware/Sensor;
    invoke-virtual {v5}, Landroid/hardware/Sensor;->getName()Ljava/lang/String;
    move-result-object v5
    invoke-virtual {v7, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move-result-object v5
    invoke-virtual {v5}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    move-result-object v5
    invoke-virtual {v6, v5}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    .line 227
    iget-object v6, p0, LlibSDL/jni/libSDL;->sManager:Landroid/hardware/SensorManager;
    iget-object v7, p0, LlibSDL/jni/libSDL;->sensorEventListener:Landroid/hardware/SensorEventListener;
    invoke-interface {v3, v9}, Ljava/util/List;->get(I)Ljava/lang/Object;
    move-result-object v5
    check-cast v5, Landroid/hardware/Sensor;
    const/4 v8, 0x3
    invoke-virtual {v6, v7, v5, v8}, Landroid/hardware/SensorManager;->registerListener(Landroid/hardware/SensorEventListener;Landroid/hardware/Sensor;I)Z
    .line 225
    add-int/lit8 v1, v1, 0x1
    goto :goto_2
.end method

Много неразберихи, но я обнаружил, что сгенерировался Java-код. Уже лучше. Я взял весь код и закинул в Android Studio, добавив сверху NDK и нативную библиотеку, которая была в декомпилированном приложении. Однако, код оказался не совсем рабочим. Вот такое содержимое получилось в onCreate:

public void onCreate(final Bundle bundle) {
        super.onCreate(bundle);
        Boolean b = true;
        Label_0115:
        while (true) {
            try {
                final int libSDLcheckloaded = libSDLproxy.libSDLcheckloaded();
                if (b) {
                    if (libSDLcheckloaded == 2) {
                        break Label_0115;
                    }
                    new AlertDialog.Builder((Context) this).setTitle((CharSequence) "Error").setMessage((CharSequence) "Incompatible SDL library version").setNeutralButton((CharSequence) "Ok", (DialogInterface$OnClickListener) new DialogInterface$OnClickListener() {
                        public void onClick(final DialogInterface dialogInterface, final int n) {
                            libSDL.this.finish();
                        }
                    }).show();
                }
                return;
            } catch (Throwable t) {
                b = false;
                new AlertDialog.Builder((Context) this).setTitle((CharSequence) "Error").setMessage((CharSequence) "Cannot load SDL library").setNeutralButton((CharSequence) "Ok", (DialogInterface$OnClickListener) new DialogInterface$OnClickListener() {
                    public void onClick(final DialogInterface dialogInterface, final int n) {
                        libSDL.this.finish();
                    }
                }).show();
                final int libSDLcheckloaded = 0;
                continue;
            }
            break;
        }
        this.requestWindowFeature(1);
        this.getWindow().setFlags(1024, 1152);
        this.setContentView((View) (this.SDLview = new libSDLview((Context) this)));
        this.sManager = (SensorManager) this.getSystemService("sensor");
        if (!libSDLconfig.CONF_DISABLE_ACCELEROMETER) {
            final List sensorList = this.sManager.getSensorList(1);
            for (int i = 0; i < sensorList.size(); ++i) {
                System.out.println("Sensor " + i + ": " + sensorList.get(i).getName());
                this.sManager.registerListener(this.sensorEventListener, (Sensor) sensorList.get(0), 3);
            }
        }
        this.setDefaultKeyMode(0);
        this.setRequestedOrientation(libSDLconfig.CONF_DEFAULT_ORIENTATION);
    }

И самое важное, что я узнал — версию используемой Activity из строки:

import android.app.Activity;

То есть библиотека поддержки v4 или v7 не используется, а метод для запроса разрешений в реальном времени есть в классе ContextCompat, который содержится в библиотеке поддержки v4.

Так же в Java-коде был вот такой вот интересный метод, где каждый continue вызывает ошибку "not a loop statement" (незначительная часть кода убрана, так как целиком он просто не влезал):

public libSDL() {
    super();
    this.MouseMode = 1;
    this.oldSimLeft = false;
    this.oldSimRight = false;
    this.oldSimUp = false;
    this.oldSimDown = false;
    this.TrackballKillMoves = false;
    this.TP_DeltaX = 0;
    this.TP_DeltaY = 0;
    this.sensorEventListener = (SensorEventListener) new SensorEventListener() {
        public void onAccuracyChanged(final Sensor sensor, final int n) {
        }
        public void onSensorChanged(final SensorEvent sensorEvent) {
            float n;
            float n2 = 0.0f;
            float n3 = 0.0f;
            Boolean oldSimRight;
            int n4;
            Boolean oldSimDown;
            Boolean oldSimUp;
            int n5;
            int n6;
            Boolean b;
            Boolean b2;
            Boolean oldSimLeft;
            int n7;
            Block_34_Outer:
            Label_0339_Outer:
            while (true) {
                Label_0332:
                while (true) {
                    Label_0302:
                    Label_0242_Outer:
                    Label_0272_Outer:
                    while (true) {
                        Label_0272:
                        while (true) {
                            Label_0242:
                            Label_0037_Outer:
                            while (true) {
                                while (true) {
                                    Label_0339:
                                    Block_8_Outer:
                                    Label_0428_Outer:
                                    while (true) {
                                        synchronized (this) {
                                            n = sensorEvent.values[0];
                                            n2 = sensorEvent.values[1];
                                            n3 = sensorEvent.values[2];
                                            if (n < 0.0f) {
                                                n = -n;
                                            }
                                            break Label_0339;
                                            while (true) {
                                                Block_29:
                                                while (true) {
                                                    Label_0080:
                                                    while (true) {
                                                        Block_6:
                                                        while (true) {
                                                            Label_0249:
                                                            {
                                                                Block_21:
                                                                {
                                                                    while (true) {
                                                                        Block_14:
                                                                        {
                                                                            Block_7:
                                                                            {
                                                                                Label_0403:
                                                                                {
                                                                                    Label_0160:
                                                                                    {
                                                                                        while (true) {
                                                                                            while (true) {
                                                                                                Label_0279:
                                                                                                {
                                                                                                    Block_18_Outer:
                                                                                                    while (true) {
                                                                                                        while (true) {
                                                                                                            Block_17:
                                                                                                            {
                                                                                                                while (true) {
                                                                                                                    Block_24:
                                                                                                                    {
                                                                                                                        while (true) {
                                                                                                                            while (true) {
                                                                                                                                while (true) {
                                                                                                                                    Label_0309:
                                                                                                                                    while (true) {
                                                                                                                                        oldSimRight = true;
                                                                                                                                        break Label_0160;
                                                                                                                                        libSDLproxy.libSDLnotifyjoystick(-(int) (3276.0f * sensorEvent.values[0]) - libSDLconfig.CONF_JOYSTICK_Y_DELTA, -(int) (3276.0f * sensorEvent.values[1]), -1);
                                                                                                                                        break Label_0339;
                                                                                                                                        libSDLproxy.libSDLnotifykey(n4, 19);
                                                                                                                                        break Label_0309;
                                                                                                                                        oldSimDown = true;
                                                                                                                                        break Label_0403;
                                                                                                                                        while (true) {
                                                                                                                                            oldSimUp = true;
                                                                                                                                            break Label_0210;
                                                                                                                                            libSDLproxy.libSDLnotifykey(n5, 20);
                                                                                                                                            break Label_0339;
                                                                                                                                            break Block_17;
                                                                                                                                            break Block_21;
                                                                                                                                            n6 = 1;
                                                                                                                                            break Label_0242;
                                                                                                                                            continue Label_0210_Outer;
                                                                                                                                        }
                                                                                                                                        n5 = 1;
                                                                                                                                        continue Label_0332;
                                                                                                                                        libSDLproxy.libSDLnotifykey(n6, 21);
                                                                                                                                        break Label_0249;
                                                                                                                                        n4 = 1;
                                                                                                                                        continue Label_0302;
                                                                                                                                        break Label_0210_Outer;
                                                                                                                                        continue Block_34_Outer;
                                                                                                                                    }
                                                                                                                                    break Block_24;
                                                                                                                                    break Block_33;
                                                                                                                                    continue Label_0242_Outer;
                                                                                                                                }
                                                                                                                                Label_0378:
                                                                                                                                {
                                                                                                                                    continue Label_0210_Outer;
                                                                                                                                }
                                                                                                                            }
                                                                                                                            oldSimLeft = true;
                                                                                                                            continue Block_18_Outer;
                                                                                                                        }
                                                                                                                    }
                                                                                                                    continue Block_23_Outer;
                                                                                                                }
                                                                                                            }
                                                                                                            continue Block_31_Outer;
                                                                                                        }
                                                                                                        libSDLproxy.libSDLnotifykey(n7, 22);
                                                                                                        break Label_0279;
                                                                                                        continue Block_8_Outer;
                                                                                                    }
                                                                                                    libSDL.this.oldSimLeft = oldSimLeft;
                                                                                                    libSDL.this.oldSimRight = oldSimRight;
                                                                                                    libSDL.this.oldSimUp = oldSimUp;
                                                                                                    libSDL.this.oldSimDown = oldSimDown;
                                                                                                    return;
                                                                                                }
                                                                                            }
                                                                                            oldSimRight = true;
                                                                                            continue Label_0210;
                                                                                        }
                                                                                        Label_0481:
                                                                                        {
                                                                                            continue Label_0339_Outer;
                                                                                        }
                                                                                    }
                                                                                    oldSimLeft = true;
                                                                                    continue Label_0272_Outer;
                                                                                }
                                                                                b2 = false;
                                                                                b = false;
                                                                                break Block_6;
                                                                            }
                                                                            oldSimDown = true;
                                                                            continue Block_8_Outer;
                                                                        }
                                                                    }
                                                                    n7 = 1;
                                                                    continue Label_0272;
                                                                }
                                                                continue Label_0242_Outer;
                                                            }
                                                            b2 = true;
                                                            continue Label_0037_Outer;
                                                        }
                                                        oldSimLeft = false;
                                                        oldSimRight = false;
                                                        oldSimUp = false;
                                                        oldSimDown = false;
                                                        continue Label_0272_Outer;
                                                    }
                                                    oldSimUp = true;
                                                    continue Label_0037_Outer;
                                                }
                                            }
                                            Label_0525:
                                            {
                                                libSDLproxy.libSDLnotifyjoystick((int) (3276.0f * sensorEvent.values[1]) - libSDLconfig.CONF_JOYSTICK_Y_DELTA, (int) (3276.0f * sensorEvent.values[0]), -1);
                                            }
                                            continue Label_0339;
                                        }
                                        if (n2 < 0.0f) {
                                            n2 = -n2;
                                        }
                                        if (n3 < 0.0f) {
                                            continue;
                                        }
                                        continue;
                                    }
                                    Label_0582:
                                    {
                                        n6 = 0;
                                    }
                                    continue Label_0242;
                                }
                                Label_0588:
                                {
                                    n7 = 0;
                                }
                                continue Label_0272;
                            }
                            Label_0594:
                            {
                                n4 = 0;
                            }
                            continue Label_0302;
                        }
                        Label_0600:
                        {
                            n5 = 0;
                        }
                        continue Label_0332;
                    }
                }
            }
        }
        ;
    }

И еще несколько native методов, которые тоже отмечались ошибкой:

public static native int libSDLcheckloaded();
public static native void libSDLcleanup();
public static native int libSDLisportrait();
public static native int libSDLmain(final String p0, final String p1);
public static native void libSDLnotifyjoystick(final int p0, final int p1, final int p2);
public static native void libSDLnotifykey(final int p0, final int p1);
public static native void libSDLnotifytouch(final int p0, final int p1, final int p2, final int p3);
public static native void libSDLnotifytrackpad(final int p0, final int p1, final int p2, final int p3);
public static native void libSDLpause();
public static native void libSDLresume();
public static native int libSDLupdatebuffer(final Buffer p0, final int p1, final int p2);

Вопрос: реально ли обновить этот проект для работы на Android M (а потом и O), не затрачивая на это месяцы? И, если да — как именно внедрять Runtime Permissions с остальными возможностями новых версий Android'a?

READ ALSO
Определить время, затраченное на запрос. Java

Определить время, затраченное на запрос. Java

Есть некая таблица с данными о работникахSLQ запрос выводит данные об определенных работниках

238
Как сделать дугу на css

Как сделать дугу на css

Как сделать просто дугу на css, пол круга

214