[Galaxy S II Themes and Apps] LeoMar75:
Hi there, I want to share this tutorial for implementing Top line battery indicator mod.

I have re-made and tweaked (for XWLA4) one of my favourite theme (Dark Theme by Mr. Megi), just to show you how it looks like!

You will find this mod with this theme on the attached zip cwm file - only for deodexed xwla4.

Watch it on youtube fullscreen mode

[YOUTUBE]Iww_Qzjq5iY&feature=youtu.be[/YOUTUBE]

I started by studying the java source code for handling battery info!

source code -> here

Then i looked into a couple of classes inside SystemUI.apk just to see where i could put my hands..

To better understand the smali code of the classes i modified, i used the java source code here, it is a bit different by the Galaxy S2 implementation but a good start point!

Requirement:

1. Decompiled SystemUI.apk with Apk Manager.

2. Some advanced understanding about editing xml file and smali code.

3. Backup SystemUI.apk first!

Before to start, i'd like to point out that i used XWLA4 firmware as base, but it should work for any firmware with some changes.

Files to be edited in SystemUI.apk:

1. res/layout/status_bar.xml

2. res/values/ids.xml

3. smali/com/android/systemui/statusbar/StatusBarService.smali

4. smali/com/android/systemui/statusbar/StatusBarView.smali

1. Editing SystemUI.apk

1.1 Editing res/layout/status_bar.xml

We need to insert a ViewImage item on the xml for displaying our battery line indicator, normal/charging

Add the following line just above <LinearLayout android:orientation="horizontal" android:id="@id/icons" android:layout_width="fill_parent" android:layout_height="fill_parent">

<ImageView android:id="@id/battery_indicator_charging" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/battery_indicator_charging" />

2 Edit res/values/ids.xml

We need to add IDs for the item we have added on the status_bar.xml

Add this line at the TOP of the file, this should be the first line!

<item type="id" name="battery_indicator_charging">false</item>

2.1 Add images to res/drawable-hdpi

We need to add the following 3 images, you will find them attached on my source code!

z_battery_indicator_charging.png

z_battery_indicator.9.png

z_battery_indicator_low.9.png

2.2 Recompile SystemUI.apk

We need to recompile the apk because we need to take care about the ID ref assigned to battery_indicator_charging, and the drawable IDs for images we have added on the previus step.

Now decompile again SystemUI.apk and open res/values/public.xml:

You should see these new entries:

<public type="drawable" name="z_battery_indicator" id="0x7f0200b8" />
<public type="drawable" name="z_battery_indicator_charging" id="0x7f0200b9" />
<public type="drawable" name="z_battery_indicator_low" id="0x7f0200ba" />
...
<public type="id" name="battery_indicator_charging" id="0x7f0a0034" />

Take note of these 3 IDS: 0x7f0200b8, 0x7f0200ba, 0x7f0a0034

Please note that in your system they can have different values.

3 Editing StatusBarService.smali

We need to intercept addIcon function and when the battery icon is passed as parameter we need to call our function updateBatteryIndicator.

Find this method:

.method public addIcon(Ljava/lang/String;IILcom/android/internal/statusbar/StatusBarIcon;)V

Add replace it with the code below

.method public addIcon(Ljava/lang/String;IILcom/android/internal/statusbar/StatusBarIcon;)V
.locals 6
.parameter "slot"
.parameter "index"
.parameter "viewIndex"
.parameter "icon"

.prologue
const-string v5, "battery"
.line 466
new-instance v0, Lcom/android/systemui/statusbar/StatusBarIconView;

invoke-direct {v0, p0, p1}, Lcom/android/systemui/statusbar/StatusBarIconView;-><init>(Landroid/content/Context;Ljava/lang/String;)V

.line 467
.local v0, view:Lcom/android/systemui/statusbar/StatusBarIconView;
invoke-virtual {v0, p4}, Lcom/android/systemui/statusbar/StatusBarIconView;->set(Lcom/android/internal/statusbar/StatusBarIcon;)Z

.line 468
iget-object v1, p0, Lcom/android/systemui/statusbar/StatusBarService;->mStatusIcons:Landroid/widget/LinearLayout;

new-instance v2, Landroid/widget/LinearLayout$LayoutParams;

iget v3, p0, Lcom/android/systemui/statusbar/StatusBarService;->mIconSize:I

iget v4, p0, Lcom/android/systemui/statusbar/StatusBarService;->mIconSize:I

invoke-direct {v2, v3, v4}, Landroid/widget/LinearLayout$LayoutParams;-><init>(II)V

invoke-virtual {v1, v0, p3, v2}, Landroid/widget/LinearLayout;->addView(Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V

invoke-virtual {v5, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

move-result v1

if-eqz v1, :cond_0

.line 410
invoke-direct {p0, p4}, Lcom/android/systemui/statusbar/StatusBarService;->updateBatteryIndicator(Lcom/android/internal/statusbar/StatusBarIcon;)V

.line 469
:cond_0
return-void
.end method

Now we need to do the same for "updateIcon" method. Find this method:

.method public updateIcon(Ljava/lang/String;IILcom/android/internal/statusbar/StatusBarIcon;Lcom/android/internal/statusbar/StatusBarIcon;)V

Replace it with the code below:

.method public updateIcon(Ljava/lang/String;IILcom/android/internal/statusbar/StatusBarIcon;Lcom/android/internal/statusbar/StatusBarIcon;)V
.locals 2
.parameter "slot"
.parameter "index"
.parameter "viewIndex"
.parameter "old"
.parameter "icon"

.prologue
.line 477
iget-object v1, p0, Lcom/android/systemui/statusbar/StatusBarService;->mStatusIcons:Landroid/widget/LinearLayout;

invoke-virtual {v1, p3}, Landroid/widget/LinearLayout;->getChildAt(I)Landroid/view/View;

move-result-object v0

check-cast v0, Lcom/android/systemui/statusbar/StatusBarIconView;

.line 478
.local v0, view:Lcom/android/systemui/statusbar/StatusBarIconView;
invoke-virtual {v0, p5}, Lcom/android/systemui/statusbar/StatusBarIconView;->set(Lcom/android/internal/statusbar/StatusBarIcon;)Z

const-string v1, "battery"

invoke-virtual {v1, p1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

move-result v1

if-eqz v1, :cond_0

.line 424
invoke-direct {p0, p5}, Lcom/android/systemui/statusbar/StatusBarService;->updateBatteryIndicator(Lcom/android/internal/statusbar/StatusBarIcon;)V

.line 479
:cond_0
return-void
.end method

It's time to add our method to handle the Update our Battery Indicator!

.method private updateBatteryIndicator(Lcom/android/internal/statusbar/StatusBarIcon;)V
.locals 2
.parameter "icon"

.prologue
.line 462
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarService;->mStatusBarView:Lcom/android/systemui/statusbar/StatusBarView;

iget-object v0, v0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

iget v1, p1, Lcom/android/internal/statusbar/StatusBarIcon;->iconLevel:I

invoke-static {v1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

move-result-object v1

invoke-virtual {v0, v1}, Landroid/widget/ImageView;->setTag(Ljava/lang/Object;)V

.line 463
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarService;->mStatusBarView:Lcom/android/systemui/statusbar/StatusBarView;

iget-object v0, v0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

iget v1, p1, Lcom/android/internal/statusbar/StatusBarIcon;->iconId:I

invoke-static {v1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

move-result-object v1

invoke-virtual {v0, v1}, Landroid/widget/ImageView;->setTag(Ljava/lang/Object;)V

.line 464
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarService;->mStatusBarView:Lcom/android/systemui/statusbar/StatusBarView;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/StatusBarView;->requestLayout()V

.line 465
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarService;->mStatusBarView:Lcom/android/systemui/statusbar/StatusBarView;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/StatusBarView;->invalidate()V

.line 466
return-void
.end method

Add this code where you prefer!

Note:

We use setTag function to store an useful info: "batteryLevel" inside the two views we created.

4 Editing StatusBarView.smali

Well on this class we need to change a lot of stuff, i advice to see my attached source code and diff it.

To sum up, this is the class responsible to display the status bar view.

We need to instantiate a "BroadcastReceiver" to intercept this intent: "android.intent.action.SCREEN_ON" That's because we don't want to play the charging animation while the screen is off.

I will report, just to let you understand it better, the java pseudo code where the view is created, here we need to do some calculation to get the correct values (width) for our Barline indicator images. In addition we are creating the animation for battery charging state.

Pseudo Java source code:

protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2, int paramInt3, int paramInt4)
{
super.onLayout(paramBoolean, paramInt1, paramInt2, paramInt3, paramInt4);
if ((!this.mShowBatteryIndicator))
{
this.mBatteryIndicator.setVisibility(8);
this.mBatteryIndicatorCharging.setVisibility(8);
this.mBatteryIndicatorCharging.clearAnimation();
}
else
{
this.mBatteryIndicator.setVisibility(0);
this.mBatteryIndicatorCharging.setVisibility(0);
int j = ((Integer)this.mBatteryIndicator.getTag()).intValue();
this.mBatteryIndicatorWidth = (j * (paramInt3 - paramInt1) / 100);
this.mBatteryIndicatorCharging.layout(paramInt3, paramInt2, paramInt3 + this.mBatteryIndicatorCharging.getMeasuredWidth(), paramInt2 + this.mBatteryIndicatorCharging.getMeasuredHeight());
int i = BATTERY_INDICATOR_ID;
if ((!this.mScreenIsOn) || (chargeIconID != ((Integer)this.mBatteryIndicatorCharging.getTag()).intValue()))
{
this.mBatteryIndicatorCharging.clearAnimation();
if (j < this.mBatteryLowLevel)
i = LOW_BATTERY_INDICATOR_ID;
}
else
{
TranslateAnimation localTranslateAnimation = new TranslateAnimation(0.0F, this.mBatteryIndicatorWidth - (paramInt3 - paramInt1), 0.0F, 0.0F);
localTranslateAnimation.setDuration(1500L);
localTranslateAnimation.setStartOffset(3500L);
localTranslateAnimation.setRepeatCount(-1);
localTranslateAnimation.setRepeatMode(1);
this.mBatteryIndicatorCharging.startAnimation(localTranslateAnimation);
}
this.mBatteryIndicator.setImageResource(i);
this.mBatteryIndicator.layout(paramInt1, paramInt2, paramInt3, paramInt2 + this.mBatteryIndicator.getDrawable().getIntrinsicHeight());
}
}

Smali code

We need to add new field member to this class: StatusBarView. You can add these lines just below: "# instance fields" at the very top!

.field mBatteryIndicator:Landroid/widget/ImageView;

.field mBatteryIndicatorCharging:Landroid/widget/ImageView;

.field private mBatteryIndicatorWidth:I

.field private mBatteryLowLevel:I

.field private mShowBatteryIndicator:Z

.field mScreenIsOn:Z

.field mIntentReceiver:Landroid/content/BroadcastReceiver;

Now we need to change the constructor of this class to set values for our field members:

Find this method:

.method public constructor <init>(Landroid/content/Context;Landroid/util/AttributeSet;)V

and replace with the one below.

.method public constructor <init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
.locals 1
.parameter "context"
.parameter "attrs"

.prologue
.line 56
invoke-direct {p0, p1, p2}, Landroid/widget/FrameLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V

.line 54
const/4 v0, 0x0

iput-boolean v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mScreenIsOn:Z

const/4 v0, 0x1

iput-boolean v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mShowBatteryIndicator:Z

.line 55
new-instance v0, Lcom/android/systemui/statusbar/StatusBarView$1;

invoke-direct {v0, p0}, Lcom/android/systemui/statusbar/StatusBarView$1;-><init>(Lcom/android/systemui/statusbar/StatusBarView;)V

iput-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mIntentReceiver:Landroid/content/BroadcastReceiver;

const v0, 0x1e

iput v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryLowLevel:I

.line 49
const/4 v0, 0x1

iput v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mStatusBarMarqueeDirection:I

.line 50
const/4 v0, 0x0

iput v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mStatusBarMarqueeRange:I

.line 57
return-void
.end method

Please note on the code above this line: const v0, 0x1e, 0x1e = 30, i set the lowbattery threshold to 30% which means that from this point, the battery charging indicator png will be used! Change it as you like!

Now we need to register our receiver for "Screen On" and "Screen Off" intents.

Find the following method

.method protected onAttachedToWindow()V

Replace with the following:

.method protected onAttachedToWindow()V
.locals 5

.prologue
.line 76
invoke-super {p0}, Landroid/widget/FrameLayout;->onAttachedToWindow()V

.line 77
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mService:Lcom/android/systemui/statusbar/StatusBarService;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/StatusBarService;->onBarViewAttached()V

.line 110
new-instance v0, Landroid/content/IntentFilter;

invoke-direct {v0}, Landroid/content/IntentFilter;-><init>()V

.line 111
.local v0, filter:Landroid/content/IntentFilter;
const-string v1, "android.intent.action.SCREEN_OFF"

invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V

.line 112
const-string v1, "android.intent.action.SCREEN_ON"

invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V

.line 113
iget-object v1, p0, Lcom/android/systemui/statusbar/StatusBarView;->mContext:Landroid/content/Context;

iget-object v2, p0, Lcom/android/systemui/statusbar/StatusBarView;->mIntentReceiver:Landroid/content/BroadcastReceiver;

const/4 v3, 0x0

new-instance v4, Landroid/os/Handler;

invoke-direct {v4}, Landroid/os/Handler;-><init>()V

invoke-virtual {v1, v2, v0, v3, v4}, Landroid/content/Context;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;)Landroid/content/Intent;

return-void
.end method

At this point we need to add a method that take care of unregister our broadcast receiver. Add the following method where you prefer.

.method protected onDetachedFromWindow()V
.locals 2

.prologue
.line 127
invoke-super {p0}, Landroid/widget/FrameLayout;->onDetachedFromWindow()V

.line 128
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mContext:Landroid/content/Context;

iget-object v1, p0, Lcom/android/systemui/statusbar/StatusBarView;->mIntentReceiver:Landroid/content/BroadcastReceiver;

invoke-virtual {v0, v1}, Landroid/content/Context;->unregisterReceiver(Landroid/content/BroadcastReceiver;)V

.line 130
return-void
.end method

Let's add a new method responsible for clipping our battery indicator png image based on the current value of mBatteryIndicatorWidth field (i.e the current level)

.method public onDraw(Landroid/graphics/Canvas;)V
.locals 4
.parameter "canvas"

.prologue
.line 224
iget-boolean v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mShowBatteryIndicator:Z

if-eqz v0, :cond_0

.line 225
invoke-virtual {p1}, Landroid/graphics/Canvas;->save()I

.line 226
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v0}, Landroid/widget/ImageView;->getLeft()I

move-result v0

iget-object v1, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v1}, Landroid/widget/ImageView;->getTop()I

move-result v1

iget v2, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorWidth:I

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v3}, Landroid/widget/ImageView;->getBottom()I

move-result v3

invoke-virtual {p1, v0, v1, v2, v3}, Landroid/graphics/Canvas;->clipRect(IIII)Z

.line 231
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v0, p1}, Landroid/widget/ImageView;->draw(Landroid/graphics/Canvas;)V

.line 232
invoke-virtual {p1}, Landroid/graphics/Canvas;->restore()V

.line 234
:cond_0
invoke-super {p0, p1}, Landroid/widget/FrameLayout;->onDraw(Landroid/graphics/Canvas;)V

.line 235
return-void
.end method

4.1 Create a new smali file: StatusBarView$1.smali

Copy the following code in your file, and save it in smali/com/android/systemui/statusbar/

.method constructor <init>(Lcom/android/systemui/statusbar/StatusBarView;)V
.locals 0
.parameter

.prologue
.line 60
iput-object p1, p0, Lcom/android/systemui/statusbar/StatusBarView$1;->this$0:Lcom/android/systemui/statusbar/StatusBarView;

invoke-direct {p0}, Landroid/content/BroadcastReceiver;-><init>()V

return-void
.end method

# virtual methods
.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V
.locals 3
.parameter "context"
.parameter "intent"

.prologue
.line 63
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView$1;->this$0:Lcom/android/systemui/statusbar/StatusBarView;

const-string v1, "android.intent.action.SCREEN_ON"

invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String;

move-result-object v2

invoke-virtual {v1, v2}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

move-result v1

iput-boolean v1, v0, Lcom/android/systemui/statusbar/StatusBarView;->mScreenIsOn:Z

.line 64
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView$1;->this$0:Lcom/android/systemui/statusbar/StatusBarView;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/StatusBarView;->requestLayout()V

.line 65
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView$1;->this$0:Lcom/android/systemui/statusbar/StatusBarView;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/StatusBarView;->invalidate()V

.line 66
return-void
.end method

Now replace the methods: "onAttachedToWindow" with the code below:

.method protected onAttachedToWindow()V
.locals 5

.prologue
.line 76
invoke-super {p0}, Landroid/widget/FrameLayout;->onAttachedToWindow()V

.line 77
iget-object v0, p0, Lcom/android/systemui/statusbar/StatusBarView;->mService:Lcom/android/systemui/statusbar/StatusBarService;

invoke-virtual {v0}, Lcom/android/systemui/statusbar/StatusBarService;->onBarViewAttached()V

.line 110
new-instance v0, Landroid/content/IntentFilter;

invoke-direct {v0}, Landroid/content/IntentFilter;-><init>()V

.line 111
.local v0, filter:Landroid/content/IntentFilter;
const-string v1, "android.intent.action.SCREEN_OFF"

invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V

.line 112
const-string v1, "android.intent.action.SCREEN_ON"

invoke-virtual {v0, v1}, Landroid/content/IntentFilter;->addAction(Ljava/lang/String;)V

.line 113
iget-object v1, p0, Lcom/android/systemui/statusbar/StatusBarView;->mContext:Landroid/content/Context;

iget-object v2, p0, Lcom/android/systemui/statusbar/StatusBarView;->mIntentReceiver:Landroid/content/BroadcastReceiver;

const/4 v3, 0x0

new-instance v4, Landroid/os/Handler;

invoke-direct {v4}, Landroid/os/Handler;-><init>()V

invoke-virtual {v1, v2, v0, v3, v4}, Landroid/content/Context;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;Ljava/lang/String;Landroid/os/Handler;)Landroid/content/Intent;

return-void
.end method

Almost finished :D , now we need to modify the method "onLayout":

search for this line: return-void and replace with goto :goto_3 then add the following code just belowe this line: goto :goto_0

:goto_3
const/4 v4, 0x0

iget-boolean v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mShowBatteryIndicator:Z

if-eqz v3, :cond_3

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v3, v4}, Landroid/widget/ImageView;->setVisibility(I)V

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v3, v4}, Landroid/widget/ImageView;->setVisibility(I)V

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v3}, Landroid/widget/ImageView;->getTag()Ljava/lang/Object;

move-result-object v3

check-cast v3, Ljava/lang/Integer;

invoke-virtual {v3}, Ljava/lang/Integer;->intValue()I

move-result v2

.local v2, batteryLevel:I
sub-int v3, p4, p2

mul-int/2addr v3, v2

div-int/lit8 v3, v3, 0x64

iput v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorWidth:I

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

iget-object v4, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v4}, Landroid/widget/ImageView;->getMeasuredWidth()I

move-result v4

add-int/2addr v4, p4

iget-object v5, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v5}, Landroid/widget/ImageView;->getMeasuredHeight()I

move-result v5

add-int/2addr v5, p3

invoke-virtual {v3, p4, p3, v4, v5}, Landroid/widget/ImageView;->layout(IIII)V

const v1, 0x7f0200b8

.local v1, batteryIndicatorDrawableId:I
iget-boolean v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mScreenIsOn:Z

if-eqz v3, :cond_4

const v4, 0x10802c3

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v3}, Landroid/widget/ImageView;->getTag()Ljava/lang/Object;

move-result-object v3

check-cast v3, Ljava/lang/Integer;

invoke-virtual {v3}, Ljava/lang/Integer;->intValue()I

move-result v3

if-eq v4, v3, :cond_4

new-instance v0, Landroid/view/animation/TranslateAnimation;

iget v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorWidth:I

sub-int v4, p4, p2

sub-int/2addr v3, v4

int-to-float v3, v3

invoke-direct {v0, v6, v3, v6, v6}, Landroid/view/animation/TranslateAnimation;-><init>(FFFF)V

.local v0, animation:Landroid/view/animation/TranslateAnimation;
const-wide/16 v3, 0x5dc

invoke-virtual {v0, v3, v4}, Landroid/view/animation/TranslateAnimation;->setDuration(J)V

const-wide/16 v3, 0xdac

invoke-virtual {v0, v3, v4}, Landroid/view/animation/TranslateAnimation;->setStartOffset(J)V

const/4 v3, -0x1

invoke-virtual {v0, v3}, Landroid/view/animation/TranslateAnimation;->setRepeatCount(I)V

const/4 v3, 0x1

invoke-virtual {v0, v3}, Landroid/view/animation/TranslateAnimation;->setRepeatMode(I)V

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v3, v0}, Landroid/widget/ImageView;->startAnimation(Landroid/view/animation/Animation;)V

.end local v0 #animation:Landroid/view/animation/TranslateAnimation;
:cond_5
:goto_2
iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v3, v1}, Landroid/widget/ImageView;->setImageResource(I)V

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

iget-object v4, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v4}, Landroid/widget/ImageView;->getDrawable()Landroid/graphics/drawable/Drawable;

move-result-object v4

invoke-virtual {v4}, Landroid/graphics/drawable/Drawable;->getIntrinsicHeight()I

move-result v4

add-int/2addr v4, p3

invoke-virtual {v3, p2, p3, p4, v4}, Landroid/widget/ImageView;->layout(IIII)V

.end local v1 #batteryIndicatorDrawableId:I
.end local v2 #batteryLevel:I
:goto_1
return-void

.restart local v1 #batteryIndicatorDrawableId:I
.restart local v2 #batteryLevel:I
:cond_4
iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v3}, Landroid/widget/ImageView;->clearAnimation()V

iget v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryLowLevel:I

if-ge v2, v3, :cond_5

const v1, 0x7f0200ba

goto :goto_2

.end local v1 #batteryIndicatorDrawableId:I
.end local v2 #batteryLevel:I
:cond_3
const/16 v5, 0x8

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicator:Landroid/widget/ImageView;

invoke-virtual {v3, v5}, Landroid/widget/ImageView;->setVisibility(I)V

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v3, v5}, Landroid/widget/ImageView;->setVisibility(I)V

iget-object v3, p0, Lcom/android/systemui/statusbar/StatusBarView;->mBatteryIndicatorCharging:Landroid/widget/ImageView;

invoke-virtual {v3}, Landroid/widget/ImageView;->clearAnimation()V

goto :goto_1
.end method

Finally, we need to adjust values to match our Ref ID (drawable images and battery_indicator ID)

chargeIconID in my pseudo code is used to verify if the phone is charging, in my attached source code you will see the line below

The following value (inside onLayout method) is used to verify if the phone is charging.

const v6, 0x10802c3

Decompile framework-res.apk and open /res/values/public.xml, search for this string: name="stat_sys_battery_charge"

<public type="drawable" name="stat_sys_battery_charge" id="0x10802c3" />

Make sure that the id you are using match with that value!

Now we need to take care about one ID used by onFinishInflate method:

const v1, 0x7f0a0034

need to match with our ID in res/values/public.xml

<public type="id" name="battery_indicator_charging" id="0x7f0a0034" />

The same for the method onLayout but this time we need to take care about 2 IDs:

const v1, 0x7f0200b8

<public type="drawable" name="z_battery_indicator" id="0x7f0200b8" />

const v1, 0x7f0200ba

<public type="drawable" name="z_battery_indicator_low" id="0x7f0200ba" />

Hope this helps you guys!