[ZTE Axon 7 Themes, Apps, and Mods] jeboo:
I figured this mod was long overdue, given that we're without Xposed on Nougat. Those who used to have the Galaxy S2/4 know how fond I am of this feature! This is a straightforward mod to add 2 buttons to the longpress power menu, specifically to reboot directly to recovery and bootloader. I'm not including a flashable zip as it won't run with stock kernel (modifies /system) and this is really intended for ROM devs to cook.

I've attached the B19 files to this post.

I will go through all the changes necessary to do the mod yourself for future bases. It will be assumed you have a basic environment (apktool/smali/baksmali) set up and some apk/jar modification experience. This is based on A2017U B19.

1. Add the buttons to the longpress menu: /system/framework/framework-zte-res.apk

- Decompile the apk and replace res/layout/global_dialog.xml with:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:orientation="vertical" android:background="#b3000000" android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:textSize="12.0sp" android:textColor="#8affffff" android:gravity="center" android:id="@id/longpress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24.0dip" android:text="@string/global_action_rboot_message" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" />
<RelativeLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="132.0dip" android:layout_marginStart="56.0dip" android:layout_alignParentStart="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/airplanemode" android:layout_width="wrap_content" android:layout_height="wrap_content">
<ImageButton android:id="@id/airplane" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:tint="#ffffffff" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_airplane" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:maxLines="2" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="132.0dip" android:layout_marginEnd="56.0dip" android:layout_alignParentEnd="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/silent_mode" android:layout_width="wrap_content" android:layout_height="wrap_content">
<ImageButton android:id="@id/silent" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:tint="#ffffffff" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_silent" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:maxLines="2" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="268.0dip" android:layout_marginStart="56.0dip" android:layout_alignParentStart="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/reset_action" android:layout_width="wrap_content" android:layout_height="wrap_content">
<ImageButton android:id="@id/reset" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_reboot" android:tint="#ffffffff" android:contentDescription="@string/global_action_reset" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_reset" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_reset" android:maxLines="2" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="268.0dip" android:layout_marginEnd="56.0dip" android:layout_alignParentEnd="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/power_action" android:layout_width="wrap_content" android:layout_height="wrap_content">
<ImageButton android:id="@id/power" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_power" android:tint="#ffffffff" android:contentDescription="@string/global_action_poweroff" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_power" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_poweroff" android:maxLines="2" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="404.0dip" android:layout_marginStart="56.0dip" android:layout_alignParentStart="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/recovery_action" android:layout_width="wrap_content" android:layout_height="wrap_content">
<ImageButton android:id="@id/recovery" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_power" android:tint="#ffffffff" android:contentDescription="@string/global_action_recovery" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_recovery" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_recovery" android:maxLines="2" />
</LinearLayout>
</RelativeLayout>
<RelativeLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="404.0dip" android:layout_marginEnd="56.0dip" android:layout_alignParentEnd="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/bootloader_action" android:layout_width="wrap_content" android:layout_height="wrap_content">
<ImageButton android:id="@id/bootloader" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_power" android:tint="#ffffffff" android:contentDescription="@string/global_action_bootloader" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_bootloader" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_bootloader" android:maxLines="2" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

- For the landscape version, replace res/layout-land/global_dialog.xml with:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:orientation="vertical" android:background="#b3000000" android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:textSize="12.0sp" android:textColor="#8affffff" android:gravity="center" android:id="@id/longpress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24.0dip" android:text="@string/global_action_rboot_message" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" />
<LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="86.0dip" android:layout_centerHorizontal="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/airplanemode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="14.0dip">
<ImageButton android:id="@id/airplane" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:tint="#ffffffff" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_airplane" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:maxLines="2" />
</LinearLayout>
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/silent_mode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="14.0dip">
<ImageButton android:id="@id/silent" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:tint="#ffffffff" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_silent" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:maxLines="2" />
</LinearLayout>
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/power_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="14.0dip">
<ImageButton android:id="@id/power" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_power" android:tint="#ffffffff" android:contentDescription="@string/global_action_poweroff" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_power" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_poweroff" android:maxLines="2" />
</LinearLayout>
</LinearLayout>
<LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="224.0dip" android:layout_centerHorizontal="true">
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/reset_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="14.0dip">
<ImageButton android:id="@id/reset" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_reboot" android:tint="#ffffffff" android:contentDescription="@string/global_action_reset" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_reset" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_reset" android:maxLines="2" />
</LinearLayout>
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/recovery_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="14.0dip">
<ImageButton android:id="@id/recovery" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_power" android:tint="#ffffffff" android:contentDescription="@string/global_action_recovery" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_recovery" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_recovery" android:maxLines="2" />
</LinearLayout>
<LinearLayout android:gravity="center_horizontal" android:orientation="vertical" android:id="@id/bootloader_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="14.0dip">
<ImageButton android:id="@id/bootloader" android:background="@drawable/circle1" android:clickable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_lock_power" android:tint="#ffffffff" android:contentDescription="@string/global_action_bootloader" android:alpha="0.9" android:paddingStart="19.0dip" android:paddingEnd="19.0dip" />
<TextView android:textSize="12.0sp" android:textColor="@color/global_action_text" android:gravity="center" android:id="@id/text_bootloader" android:paddingTop="10.0dip" android:layout_width="110.0dip" android:layout_height="wrap_content" android:text="@string/global_action_bootloader" android:maxLines="2" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

It should be mentioned I simply reused the power button graphic for the additional buttons. You can customize the buttons by generating vector xml and replacing ic_lock_recovery/bootloader.xml.

(If you do generate nice icons, please post them!)

2. Add the appropriate IDs/strings/xml to framework-zte-res.apk

- add to res/values/ids.xml

<item type="id" name="recovery_action">false</item>
<item type="id" name="bootloader_action">false</item>
<item type="id" name="recovery" />
<item type="id" name="bootloader" />
<item type="id" name="text_recovery" />
<item type="id" name="text_bootloader" />

- add to res/values/strings.xml

<string name="global_action_recovery">Recovery</string>
<string name="global_action_bootloader">Bootloader</string>

- in res/drawable, copy ic_lock_power.xml to ic_lock_recovery.xml, ic_lock_bootloader.xml (comment at end of #1 applies here)

3. Build framework-zte-res.apk using apktool, which is nice enough to assign all the new IDs needed. Now decompile the new apk and open res/values/public.xml to obtain two IDs

used for step 4 smali changes:

<public type="id" name="recovery" id="[COLOR="Red"]0x06060067[/COLOR]" />
<public type="id" name="bootloader" id="[COLOR="red"]0x06060068[/COLOR]" />

You must save those two IDs somewhere for the next step. If you don't, you risk bootlooping or worse!

4. Our target for the actual code changes is GlobalActions.smali in services.odex. Search for '.method private createDialogMF40' and find the following code:

new-instance v6, Lcom/android/server/policy/GlobalActions$7;

invoke-direct {v6, p0}, Lcom/android/server/policy/GlobalActions$7;-><init>(Lcom/android/server/policy/GlobalActions;\V

invoke-virtual {v3, v6}, Landroid/view/View;->setOnClickListener(Landroid/view/View$OnClickListener;)V

Just after that last line will be our insertion point for the following code:

iget-object v6, p0, Lcom/android/server/policy/GlobalActions;->contentView:Landroid/view/View;

const v9, [COLOR="red"]0x6060067[/COLOR]

invoke-virtual {v6, v9}, Landroid/view/View;->findViewById(I)Landroid/view/View;

move-result-object v3

.line 270
.local v3, "recoveryAction":Landroid/view/View;
new-instance v6, Lcom/android/server/policy/GlobalActions$19;

invoke-direct {v6, p0}, Lcom/android/server/policy/GlobalActions$19;-><init>(Lcom/android/server/policy/GlobalActions;)V

invoke-virtual {v3, v6}, Landroid/view/View;->setOnClickListener(Landroid/view/View$OnClickListener;)V

iget-object v6, p0, Lcom/android/server/policy/GlobalActions;->contentView:Landroid/view/View;

const v9, [COLOR="red"]0x6060068[/COLOR]

invoke-virtual {v6, v9}, Landroid/view/View;->findViewById(I)Landroid/view/View;

move-result-object v3

.line 270
.local v3, "bootloaderAction":Landroid/view/View;
new-instance v6, Lcom/android/server/policy/GlobalActions$20;

invoke-direct {v6, p0}, Lcom/android/server/policy/GlobalActions$20;-><init>(Lcom/android/server/policy/GlobalActions;)V

invoke-virtual {v3, v6}, Landroid/view/View;->setOnClickListener(Landroid/view/View$OnClickListener;)V

5. Now we have associated our new buttons with GlobalActions$19 & 20 above. To create these two files, used GlobalActions$7.smali (which is the reboot code) as a template. Be sure to change any $7 to $19 / $20 in the appropriate files. Our last modifications are simple one-liners to direct the reboot behavior.

Find 'const/4 v3, 0x0' around line 69 and change to:

GlobalActions$19.smali:

const-string/jumbo v3, "recovery"

GlobalActions$20.smali:

const-string/jumbo v3, "bootloader"

Compile your changes and update services.jar. You are now ready to flash the new framework-zte-res.apk and services.jar to /system/framework. Reboot and cross your fingers!

Version History:

1.0(3/26/17): Initial release

1.1 (3/29/17): Moved portrait layout up 80 pixels to center vertically