[Samsung Galaxy S 5 Unified Development] tdunham:
Android L Ammended Guide

- additional changes here for Android 5.x

Additional android.policy.jar smali edits for android L:

\smali\com\android\internal\policy\impl\PhoneWindowManager.smali

Add new method to the bottom of this smali

.method handleVolumeKey(II)V
.locals 6

const/16 v5, 0x18

const/4 v2, 0x1

const/4 v3, -0x1

invoke-static {}, Lcom/android/internal/policy/impl/PhoneWindowManager;->getAudioService()Landroid/media/IAudioService;

move-result-object v0

if-nez v0, :cond_0

:goto_0
return-void

:cond_0
:try_start_0
iget-object v4, p0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBroadcastWakeLock:Landroid/os/PowerManager$WakeLock;

invoke-virtual {v4}, Landroid/os/PowerManager$WakeLock;->acquire()V

const/4 v4, 0x3

if-ne p1, v4, :cond_2

if-ne p2, v5, :cond_1

:goto_1
iget-object v3, p0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mContext:Landroid/content/Context;

invoke-virtual {v3}, Landroid/content/Context;->getOpPackageName()Ljava/lang/String;

move-result-object v3

invoke-interface {v0, p1, v2, v3}, Landroid/media/IAudioService;->adjustLocalOrRemoteStreamVolume(IILjava/lang/String;)V
:try_end_0
.catch Landroid/os/RemoteException; {:try_start_0 .. :try_end_0} :catch_0
.catchall {:try_start_0 .. :try_end_0} :catchall_0

:goto_2
iget-object v2, p0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBroadcastWakeLock:Landroid/os/PowerManager$WakeLock;

invoke-virtual {v2}, Landroid/os/PowerManager$WakeLock;->release()V

goto :goto_0

:cond_1
move v2, v3

goto :goto_1

:cond_2
if-ne p2, v5, :cond_3

:goto_3
const/4 v3, 0x0

:try_start_1
iget-object v4, p0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mContext:Landroid/content/Context;

invoke-virtual {v4}, Landroid/content/Context;->getOpPackageName()Ljava/lang/String;

move-result-object v4

invoke-interface {v0, p1, v2, v3, v4}, Landroid/media/IAudioService;->adjustStreamVolume(IIILjava/lang/String;)V
:try_end_1
.catch Landroid/os/RemoteException; {:try_start_1 .. :try_end_1} :catch_0
.catchall {:try_start_1 .. :try_end_1} :catchall_0

goto :goto_2

:catch_0
move-exception v1

:try_start_2
const-string v2, "WindowManager"

new-instance v3, Ljava/lang/StringBuilder;

invoke-direct {v3}, Ljava/lang/StringBuilder;-><init>()V

const-string v4, "IAudioService.adjust*StreamVolume() threw RemoteException "

invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

move-result-object v3

invoke-virtual {v3, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder;

move-result-object v3

invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v3

invoke-static {v2, v3}, Landroid/util/Log;->w(Ljava/lang/String;Ljava/lang/String;)I
:try_end_2
.catchall {:try_start_2 .. :try_end_2} :catchall_0

iget-object v2, p0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBroadcastWakeLock:Landroid/os/PowerManager$WakeLock;

invoke-virtual {v2}, Landroid/os/PowerManager$WakeLock;->release()V

goto :goto_0

:cond_3
move v2, v3

goto :goto_3

:catchall_0
move-exception v2

iget-object v3, p0, Lcom/android/internal/policy/impl/PhoneWindowManager;->mBroadcastWakeLock:Landroid/os/PowerManager$WakeLock;

invoke-virtual {v3}, Landroid/os/PowerManager$WakeLock;->release()V

throw v2
.end method

framework.jar smali edits:

(New in Android L to install missing code)

smali\android\media\AudioManager.smali

Add new method to the bottom of this smali

.method public isLocalOrRemoteMusicActive()Z
.locals 4

invoke-static {}, Landroid/media/AudioManager;->getService()Landroid/media/IAudioService;

move-result-object v1

:try_start_0
invoke-interface {v1}, Landroid/media/IAudioService;->isLocalOrRemoteMusicActive()Z
:try_end_0
.catch Landroid/os/RemoteException; {:try_start_0 .. :try_end_0} :catch_0

move-result v2

:goto_0
return v2

:catch_0
move-exception v0

sget-object v2, Landroid/media/AudioManager;->TAG:Ljava/lang/String;

const-string v3, "Dead object in isLocalOrRemoteMusicActive()"

invoke-static {v2, v3, v0}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I

const/4 v2, 0x0

goto :goto_0
.end method

smali\android\media\AudioService.smali

Add new methods to the bottom of this smali

.method public adjustLocalOrRemoteStreamVolume(IILjava/lang/String;)V
.locals 4

const/16 v3, 0xa

const/4 v2, 0x3

const/4 v1, 0x0

invoke-static {v2, v1}, Landroid/media/AudioSystem;->isStreamActive(II)Z

move-result v0

if-eqz v0, :cond_1

invoke-virtual {p0, v2, p2, v1, p3}, Landroid/media/AudioService;->adjustStreamVolume(IIILjava/lang/String;)V

:cond_0
:goto_0
return-void

:cond_1
iget-object v0, p0, Landroid/media/AudioService;->mMediaFocusControl:Landroid/media/MediaFocusControl;

invoke-virtual {v0, v2}, Landroid/media/MediaFocusControl;->checkUpdateRemoteStateIfActive(I)Z

move-result v0

if-eqz v0, :cond_2

iget-object v0, p0, Landroid/media/AudioService;->mMediaFocusControl:Landroid/media/MediaFocusControl;

invoke-virtual {v0, v2, p2, v1}, Landroid/media/MediaFocusControl;->adjustRemoteVolume(III)V

goto :goto_0

:cond_2
invoke-static {v3, v1}, Landroid/media/AudioSystem;->isStreamActive(II)Z

move-result v0

if-eqz v0, :cond_0

invoke-virtual {p0, v3, p2, v1, p3}, Landroid/media/AudioService;->adjustStreamVolume(IIILjava/lang/String;)V

goto :goto_0
.end method

.method public isLocalOrRemoteMusicActive()Z
.locals 4

const/4 v3, 0x3

const/4 v0, 0x1

const/4 v1, 0x0

invoke-static {v3, v1}, Landroid/media/AudioSystem;->isStreamActive(II)Z

move-result v2

if-eqz v2, :cond_1

:cond_0
:goto_0
return v0

:cond_1
iget-object v2, p0, Landroid/media/AudioService;->mMediaFocusControl:Landroid/media/MediaFocusControl;

invoke-virtual {v2, v3}, Landroid/media/MediaFocusControl;->checkUpdateRemoteStateIfActive(I)Z

move-result v2

if-nez v2, :cond_0

invoke-static {v3, v1}, Landroid/media/AudioSystem;->isStreamActiveRemotely(II)Z

move-result v2

if-nez v2, :cond_0

move v0, v1

goto :goto_0
.end method

smali\android\media\IAudioService$Stub$Proxy.smali

Add new method to the bottom of this smali

.method public adjustLocalOrRemoteStreamVolume(IILjava/lang/String;)V
.locals 5
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation

invoke-static {}, Landroid/os/Parcel;->obtain()Landroid/os/Parcel;

move-result-object v0

:try_start_0
const-string v1, "android.media.IAudioService"

invoke-virtual {v0, v1}, Landroid/os/Parcel;->writeInterfaceToken(Ljava/lang/String;)V

invoke-virtual {v0, p1}, Landroid/os/Parcel;->writeInt(I)V

invoke-virtual {v0, p2}, Landroid/os/Parcel;->writeInt(I)V

invoke-virtual {v0, p3}, Landroid/os/Parcel;->writeString(Ljava/lang/String;)V

iget-object v1, p0, Landroid/media/IAudioService$Stub$Proxy;->mRemote:Landroid/os/IBinder;

const/4 v2, 0x4

const/4 v3, 0x0

const/4 v4, 0x1

invoke-interface {v1, v2, v0, v3, v4}, Landroid/os/IBinder;->transact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
:try_end_0
.catchall {:try_start_0 .. :try_end_0} :catchall_0

invoke-virtual {v0}, Landroid/os/Parcel;->recycle()V

return-void

:catchall_0
move-exception v1

invoke-virtual {v0}, Landroid/os/Parcel;->recycle()V

throw v1
.end method

smali\android\media\IAudioService$Stub.smali

New lines are in BLUE, replace the lines that are in PURPLE

# static fields
.field private static final DESCRIPTOR:Ljava/lang/String; = "android.media.IAudioService"

.field static final TRANSACTION_abandonAudioFocus:I = 0x28

[COLOR="Blue"].field static final TRANSACTION_adjustLocalOrRemoteStreamVolume:I = 0x4
[/COLOR]
[COLOR="Purple"].field static final TRANSACTION_adjustMasterVolume:I = 0x7

.field static final TRANSACTION_adjustStreamVolume:I = 0x6

.field static final TRANSACTION_adjustSuggestedStreamVolume:I = 0x5
[/COLOR]
[COLOR="Blue"].field static final TRANSACTION_adjustVolume:I = 0x2
[/COLOR]
.field static final TRANSACTION_avrcpSupportsAbsoluteVolume:I = 0x20

.field static final TRANSACTION_disableSafeMediaVolume:I = 0x3e

[COLOR="Purple"].field static final TRANSACTION_dismissVolumePanel:I = 0x53[/COLOR]

[COLOR="Blue"].field static final TRANSACTION_dispatchMediaKeyEventUnderWakelock:I = 0x2f
[/COLOR]
.field static final TRANSACTION_forceRemoteSubmixFullVolume:I = 0xa

.field static final TRANSACTION_forceVolumeControlStream:I = 0x33

.field static final TRANSACTION_getActiveStreamType:I = 0x48

.field static final TRANSACTION_getCurrentAudioFocus:I = 0x2a

.field static final TRANSACTION_getCurrentAudioFocusPackageName:I = 0x4e

.field static final TRANSACTION_getLastAudibleMasterVolume:I = 0x12

.field static final TRANSACTION_getLastAudibleStreamVolume:I = 0x11

.field static final TRANSACTION_getMasterMaxVolume:I = 0x10

.field static final TRANSACTION_getMasterStreamType:I = 0x36

.field static final TRANSACTION_getMasterVolume:I = 0xe

.field static final TRANSACTION_getMode:I = 0x1a

.field static final TRANSACTION_getRemoteControlClientNowPlayingEntries:I = 0x44

[COLOR="Blue"].field static final TRANSACTION_getRemoteStreamMaxVolume:I = 0x40
[/COLOR]

Same smali search for adjustMasterVolume and replace these two lines:

Before:

invoke-virtual {p0, v1, v2, v3}, Landroid/media/IAudioService$Stub;->adjustMasterVolume(IILjava/lang/String;)V

invoke-virtual {p3}, Landroid/os/Parcel;->writeNoException()V

After:

move-object/from16 v0, p0

invoke-virtual {p0, v1, v2, v3}, Landroid/media/IAudioService$Stub;->adjustLocalOrRemoteStreamVolume(IILjava/lang/String;)V

smali\android\media\IAudioService.smali

Add these methods to the bottom of this smali

.method public abstract adjustLocalOrRemoteStreamVolume(IILjava/lang/String;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method
.method public abstract adjustVolume(IILjava/lang/String;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract dispatchMediaKeyEvent(Landroid/view/KeyEvent;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract dispatchMediaKeyEventUnderWakelock(Landroid/view/KeyEvent;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract getRemoteStreamMaxVolume()I
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract getRemoteStreamVolume()I
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract isLocalOrRemoteMusicActive()Z
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract registerMediaButtonEventReceiverForCalls(Landroid/content/ComponentName;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract registerMediaButtonIntent(Landroid/app/PendingIntent;Landroid/content/ComponentName;Landroid/os/IBinder;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract registerRemoteControlClient(Landroid/app/PendingIntent;Landroid/media/IRemoteControlClient;Ljava/lang/String;)I
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract registerRemoteVolumeObserverForRcc(ILandroid/media/IRemoteVolumeObserver;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract setRingerMode(I)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract setSmartVoumeEnable(Z)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract unregisterRemoteControlDisplay(Landroid/media/IRemoteControlDisplay;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract updateRemoteControlClientMetadata(IILandroid/media/Rating;)V
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

.method public abstract verifyX509CertChain(I[BLjava/lang/String;Ljava/lang/String;)I
.annotation system Ldalvik/annotation/Throws;
value = {
Landroid/os/RemoteException;
}
.end annotation
.end method

CustomSettings.apk edits

This app adds the toggle without the need for the SecSettings edits.

The edits shown are if you are already running the customsettings app.

The basic apk with the edits already included is attached at the bottom of this post.

res/values/strings.xml add new lines in BLUE:

[COLOR="Blue"] <string name="volbtn_music_controls_title">Music Control</string>
<string name="volbtn_music_controls_summary">Customize volume rocker action</string>
<string name="volbtn_toggle_title">Music Control</string>
<string name="volbtn_vol_up_title">Volume Up action</string>
<string name="volbtn_vol_up_summary">%s</string>
<string name="volbtn_vol_down_title">Volume Down action</string>
<string name="volbtn_vol_down_summary">%s</string>
<string name="volbtn_timeout_title">Button delay</string>
<string name="volbtn_timeout_summary">%s</string>
[/COLOR]</resources>

res/values/arrays add new lines in BLUE

[COLOR="Blue"] <string-array name="volbtn_action_entries">
<item>Next</item>
<item>Pause</item>
<item>Play</item>
<item>Play/Pause</item>
<item>Previous</item>
<item>Stop</item>
</string-array>
<string-array name="volbtn_action_values">
<item>87</item>
<item>127</item>
<item>126</item>
<item>85</item>
<item>88</item>
<item>86</item>
</string-array>
<string-array name="volbtn_timeout_entries">
<item>100ms</item>
<item>150ms</item>
<item>200ms</item>
<item>250ms</item>
<item>300ms</item>
<item>350ms</item>
<item>400ms</item>
<item>450ms</item>
<item>500ms</item>
</string-array>
<string-array name="volbtn_timeout_values">
<item>100</item>
<item>150</item>
<item>200</item>
<item>250</item>
<item>300</item>
<item>350</item>
<item>400</item>
<item>450</item>
<item>500</item>
</string-array>[/COLOR]
</resources>

res/xml/preferences.xml

This is where we add the menu items.

Add new lines shown in BLUE

[COLOR="Blue"] <PreferenceScreen android:title="@string/volbtn_music_controls_title" android:summary="@string/volbtn_music_controls_summary">
<SwitchPreference android:title="@string/volbtn_toggle_title" android:key="volbtn_music_controls" android:defaultValue="true" />
<ListPreference android:persistent="false" android:entries="@array/volbtn_timeout_entries" android:title="@string/volbtn_timeout_title" android:key="volbtn_timeout" android:summary="@string/volbtn_timeout_summary" android:dependency="volbtn_music_controls" android:entryValues="@array/volbtn_timeout_values" />
<ListPreference android:persistent="false" android:entries="@array/volbtn_action_entries" android:title="@string/volbtn_vol_up_title" android:key="volbtn_vol_up" android:summary="@string/volbtn_vol_up_summary" android:dependency="volbtn_music_controls" android:entryValues="@array/volbtn_action_values" />
<ListPreference android:persistent="false" android:entries="@array/volbtn_action_entries" android:title="@string/volbtn_vol_down_title" android:key="volbtn_vol_down" android:summary="@string/volbtn_vol_down_summary" android:dependency="volbtn_music_controls" android:entryValues="@array/volbtn_action_values" />
</PreferenceScreen>
[/COLOR]</PreferenceScreen>