(S7e dump)
reo GlobalActions has been moved from services.jar to systemui. Systemui has not got the reboot permission. So, you can try to add the permission to systemui manifest, but.. i think you will have problems on clean installs.
So, a simple way to solve this small inconvenience is to send a broadcast to an existing receiver in services.jar (or other apk, jar or wichever having reboot permissions).
In this guide i will not do the power menu toggle to go to recovery / download but a code to reboot the phone from sysui in recovery / download mode.
I will use one of the existing receivers in services.jar. We will register our action in that receiver. We will mod the receiver to check if our action was received. If so, we check what action we need to run (go to recovery or download) and we will run the action.
You can adapt easily this guide with your own action name and extras added to the intent. You can also easily use it in other ways or purposes.
1.- Decomplile services.jar
- Edit com/android/server/policy/PhoneWindowManager.smali
- Look for this method
Inside the method look for this code and add the following three lines.
So, in my case i will use the action "com.mods.grx.SERVICES" in the existing mDockReceiver
Now wee need to know what smali mDockReeiver is. Easy, go the constructor
look for the initialization of the receiver. Something like this
So, in this case the receiver code is in PhoneWindowManager$10.smali
- Edit PhoneWindowManager$10.smali and add the followng code
what this code does is to check if the received action is our action. If so, we are expecting that the intent got a extra value ("ACTION") of type string. You could have registered more actions, but..for what?
We retreive the extra "ACTION" string value and we call to a method in PhoneWindowManager called grxOnActionReceived passing the string value
- Edit again PhoneWindowmanager.smal and at the end of the smali add this method
So, when we receive the broadcast, we check if it was sent with our action, and if so, we check what we have to do (getting the extra "ACTION" value). If we want to go to recovery or download.
So, finally, let´s add those 2 methods called from grxOnActionReceived . One for going to recovery and the other one for going to download.
2.- Now let´s add the buttons to systemui. Decompile Systemui
- in the attached file you will find the following:
. 2 pngs, copy them to drawable-xxhdpi (thanks to @Peugeot73 for these pngs, we are using a lot, he he)
. a txt with the strings to add
. 2 smalies: copy both to smali\com\android\systemui\globalactions folder
Now let´s add the buttons.
- Edit com/android/systemui/globalactions/GlobalActionsDialog.smali
Add this fields
Look for this method
inside it look for these instructions and add the following line
Now look for this method
add the following lines
Finally, at the end of the smali add this method
Compile and done
Compiling systemui
i am using apktool 2.3.1. I have faced the following problems compiling the ui.
- a .9.png corrupted -> rename it to .png (remove .9)
- classes dex with many methods error -> go to smal folder, cut android folder and paste it inside smali_classes2 folder
- Once it is compiled, open both original ui and compiled with winrar (better with no comprenssion). Then:
- remove in the original the res folder (thanks to @sannoc69 for this), and also classes and classes2
- drag res, resources.ascr, classes and classes2.dex from compiled to original
reo GlobalActions has been moved from services.jar to systemui. Systemui has not got the reboot permission. So, you can try to add the permission to systemui manifest, but.. i think you will have problems on clean installs.
So, a simple way to solve this small inconvenience is to send a broadcast to an existing receiver in services.jar (or other apk, jar or wichever having reboot permissions).
In this guide i will not do the power menu toggle to go to recovery / download but a code to reboot the phone from sysui in recovery / download mode.
I will use one of the existing receivers in services.jar. We will register our action in that receiver. We will mod the receiver to check if our action was received. If so, we check what action we need to run (go to recovery or download) and we will run the action.
You can adapt easily this guide with your own action name and extras added to the intent. You can also easily use it in other ways or purposes.
1.- Decomplile services.jar
- Edit com/android/server/policy/PhoneWindowManager.smali
- Look for this method
Código:
.method public init(Landroid/content/Context;Landroid/view/IWindowManager;Landroid/view/WindowManagerPolicy$WindowManagerFuncs;)V
Inside the method look for this code and add the following three lines.
Código:
const-string/jumbo v2, "android.intent.action.DOCK_EVENT"
move-object/from16 v0, v19
invoke-virtual {v0, v2}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V
######
const-string/jumbo v2, "com.mods.grx.SERVICES"
move-object/from16 v0, v19
invoke-virtual {v0, v2}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V
######
move-object/from16 v0, p0
iget-object v2, v0, Lcom/android/server/policy/PhoneWindowManager;->mDockReceiver:Landroid/content/BroadcastReceiver;
move-object/from16 v0, p1
So, in my case i will use the action "com.mods.grx.SERVICES" in the existing mDockReceiver
Now wee need to know what smali mDockReeiver is. Easy, go the constructor
Código:
.method public constructor <init>()V
look for the initialization of the receiver. Something like this
Código:
iput-object v0, p0, Lcom/android/server/policy/PhoneWindowManager;->mScreenshotTimeout:Ljava/lang/Runnable;
new-instance v0, Lcom/android/server/policy/PhoneWindowManager$10; ####
invoke-direct {v0, p0}, Lcom/android/server/policy/PhoneWindowManager$10;-><init>(Lcom/android/server/policy/PhoneWindowManager;)V ###
iput-object v0, p0, Lcom/android/server/policy/PhoneWindowManager;->mDockReceiver:Landroid/content/BroadcastReceiver; ####
new-instance v0, Lcom/android/server/policy/PhoneWindowManager$11;
So, in this case the receiver code is in PhoneWindowManager$10.smali
- Edit PhoneWindowManager$10.smali and add the followng code
Código:
# virtual methods
.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V
.locals 5
############
invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String;
move-result-object v3
const-string/jumbo v2, "com.mods.grx.SERVICES"
invoke-virtual {v2, v3}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v2
if-eqz v2, :cond_go
const-string v2, "ACTION"
invoke-virtual {p2, v2}, Landroid/content/Intent;->getStringExtra(Ljava/lang/String;)Ljava/lang/String;
move-result-object v3
iget-object v2, p0, Lcom/android/server/policy/PhoneWindowManager$10;->this$0:Lcom/android/server/policy/PhoneWindowManager;
invoke-virtual {v2, v3}, Lcom/android/server/policy/PhoneWindowManager;->grxOnActionReceived(Ljava/lang/String;)V
return-void
:cond_go
#####
what this code does is to check if the received action is our action. If so, we are expecting that the intent got a extra value ("ACTION") of type string. You could have registered more actions, but..for what?
We retreive the extra "ACTION" string value and we call to a method in PhoneWindowManager called grxOnActionReceived passing the string value
- Edit again PhoneWindowmanager.smal and at the end of the smali add this method
Código:
.method public grxOnActionReceived(Ljava/lang/String;)V
.locals 3
if-eqz p1, :cond_exit
const-string v0, "RECOVERY"
invoke-virtual {p1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v1
if-eqz v1, :cond_checkdownload
invoke-virtual {p0}, Lcom/android/server/policy/PhoneWindowManager;->grxGoToRecovery()V
:cond_exit
:goto_exit
return-void
:cond_checkdownload
const-string v0, "DOWNLOAD"
invoke-virtual {p1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v1
if-eqz v1, :cond_exit
invoke-virtual {p0}, Lcom/android/server/policy/PhoneWindowManager;->grxGoToDownload()V
goto :goto_exit
.end method
So, when we receive the broadcast, we check if it was sent with our action, and if so, we check what we have to do (getting the extra "ACTION" value). If we want to go to recovery or download.
So, finally, let´s add those 2 methods called from grxOnActionReceived . One for going to recovery and the other one for going to download.
Código:
.method public grxGoToDownload()V
.locals 5
const-string/jumbo v0, "power"
invoke-static {v0}, Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
move-result-object v0
invoke-static {v0}, Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager;
move-result-object v0
const/4 v1, 0x0
const-string v2, "download"
const/4 v3, 0x0
invoke-interface {v0, v1, v2, v3}, Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V
return-void
.end method
.method public grxGoToRecovery()V
.locals 5
const-string/jumbo v0, "power"
invoke-static {v0}, Landroid/os/ServiceManager;->getService(Ljava/lang/String;)Landroid/os/IBinder;
move-result-object v0
invoke-static {v0}, Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager;
move-result-object v0
const/4 v1, 0x0
const-string/jumbo v2, "recovery"
const/4 v3, 0x0
invoke-interface {v0, v1, v2, v3}, Landroid/os/IPowerManager;->reboot(ZLjava/lang/String;Z)V
return-void
.end method
2.- Now let´s add the buttons to systemui. Decompile Systemui
- in the attached file you will find the following:
. 2 pngs, copy them to drawable-xxhdpi (thanks to @Peugeot73 for these pngs, we are using a lot, he he)
. a txt with the strings to add
. 2 smalies: copy both to smali\com\android\systemui\globalactions folder
Now let´s add the buttons.
- Edit com/android/systemui/globalactions/GlobalActionsDialog.smali
Add this fields
Código:
# instance fields
####
.field private mGrxRecoveryAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction;
.field private mGrxDownloadAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction;
#####
Look for this method
Código:
.method private makeActionsItems()V
inside it look for these instructions and add the following line
Código:
iput-object v0, p0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mProKioskAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$ToggleAction;
new-instance v1, Lcom/android/systemui/globalactions/GlobalActionsDialog$28;
sget-boolean v0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->sSupportBlackWhiteTheme:Z
if-eqz v0, :cond_7
const v0, 0x1080aab
:goto_6
const v2, 0x10403ac
invoke-direct {v1, p0, v0, v2}, Lcom/android/systemui/globalactions/GlobalActionsDialog$28;-><init>(Lcom/android/systemui/globalactions/GlobalActionsDialog;II)V
iput-object v1, p0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mRestartAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction; # after the iput-object of mRestart add the following line
####
invoke-virtual {p0}, Lcom/android/systemui/globalactions/GlobalActionsDialog;->grxBuildCustomButtons()V #add this line
#####
iget-boolean v0, p0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->SUPPORT_BIKEMODE_ACTION:Z
Now look for this method
Código:
.method private createDialog()Lcom/android/systemui/globalactions/GlobalActionsDialog$ActionsDialog;
add the following lines
Código:
goto :goto_3
:cond_b
const-string/jumbo v25, "restart" ### look for this
move-object/from16 v0, v25
invoke-virtual {v0, v6}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v25
if-eqz v25, :cond_c
move-object/from16 v0, p0
iget-object v0, v0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mItems:Ljava/util/ArrayList;
move-object/from16 v25, v0
move-object/from16 v0, p0
iget-object v0, v0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mRestartAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction; #### look for this
move-object/from16 v28, v0
move-object/from16 v0, v25
move-object/from16 v1, v28
invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z
####### add this block
move-object/from16 v0, p0
iget-object v0, v0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mItems:Ljava/util/ArrayList;
move-object/from16 v1, p0
iget-object v1, v1, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mGrxRecoveryAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction;
invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z
move-object/from16 v0, p0
iget-object v0, v0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mItems:Ljava/util/ArrayList;
move-object/from16 v1, p0
iget-object v1, v1, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mGrxDownloadAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction;
invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z
######### before the goto
goto/16 :goto_2
Finally, at the end of the smali add this method
Código:
.method public grxBuildCustomButtons()V
.locals 7
iget-object v0, p0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mContext:Landroid/content/Context;
invoke-virtual {v0}, Landroid/content/Context;->getPackageName()Ljava/lang/String;
move-result-object v3
iget-object v0, p0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mContext:Landroid/content/Context;
invoke-virtual {v0}, Landroid/content/Context;->getResources()Landroid/content/res/Resources;
move-result-object v0
const-string v2, "drawable"
const-string v1, "grx_pow_recovery"
invoke-virtual {v0, v1, v2, v3}, Landroid/content/res/Resources;->getIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
move-result v4
const-string v2, "string"
const-string v1, "gs_reb_recovery"
invoke-virtual {v0, v1, v2, v3}, Landroid/content/res/Resources;->getIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
move-result v5
new-instance v1, Lcom/android/systemui/globalactions/GlobalActionsDialog$GrxRecovery;
invoke-direct {v1, p0, v4, v5}, Lcom/android/systemui/globalactions/GlobalActionsDialog$GrxRecovery;-><init>(Lcom/android/systemui/globalactions/GlobalActionsDialog;II)V
iput-object v1, p0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mGrxRecoveryAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction;
const-string v2, "drawable"
const-string v1, "grx_pow_download"
invoke-virtual {v0, v1, v2, v3}, Landroid/content/res/Resources;->getIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
move-result v4
const-string v2, "string"
const-string v1, "gs_reb_download"
invoke-virtual {v0, v1, v2, v3}, Landroid/content/res/Resources;->getIdentifier(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
move-result v5
new-instance v1, Lcom/android/systemui/globalactions/GlobalActionsDialog$GrxDownload;
invoke-direct {v1, p0, v4, v5}, Lcom/android/systemui/globalactions/GlobalActionsDialog$GrxDownload;-><init>(Lcom/android/systemui/globalactions/GlobalActionsDialog;II)V
iput-object v1, p0, Lcom/android/systemui/globalactions/GlobalActionsDialog;->mGrxDownloadAction:Lcom/android/systemui/globalactions/GlobalActionsDialog$SinglePressAction;
return-void
.end method
Compile and done
Compiling systemui
i am using apktool 2.3.1. I have faced the following problems compiling the ui.
- a .9.png corrupted -> rename it to .png (remove .9)
- classes dex with many methods error -> go to smal folder, cut android folder and paste it inside smali_classes2 folder
- Once it is compiled, open both original ui and compiled with winrar (better with no comprenssion). Then:
- remove in the original the res folder (thanks to @sannoc69 for this), and also classes and classes2
- drag res, resources.ascr, classes and classes2.dex from compiled to original