[Nexus S Android Development] atl4ntis:
This howto will teach you how to add a quad lockscreen with phone and messaging to any jb rom in 2 ways:

[SMALI]: you're going to modify already compiled files, you will need a basic knowledge about decompiling/recompiling/editing jar, apk and smali files.

[JAVA]: you're going to modify the JB source code, you will need a basic knowledge about java and how to compile an AOSP.

Choose your path and always follow the instuction with that tag.

framework resources editing:

[SMALI]

Decompile your framework-res.apk

Put ic_lockscreen_phone_activated.png, ic_lockscreen_phone_normal.png, ic_lockscreen_sms_activated.png, ic_lockscreen_sms_normal.png in /res/drawable-hdpi/

[JAVA]

Put ic_lockscreen_phone_activated.png, ic_lockscreen_phone_normal.png, ic_lockscreen_sms_activated.png, ic_lockscreen_sms_normal.png in	/frameworks/base/core/res/res/drawable-hdpi/

[SMALI]

Put ic_lockscreen_phone.xml, ic_lockscreen_sms.xml in /res/drawable/

[JAVA]

Put ic_lockscreen_phone.xml, ic_lockscreen_sms.xml in /frameworks/base/core/res/res/drawable/

Add the necessary entries in /frameworks/base/core/res/res/values/public.xml:

<java-symbol type="drawable" name="ic_lockscreen_sms" />
<java-symbol type="drawable" name="ic_lockscreen_phone" />

[SMALI]

Open /res/values/arrays.xml

[JAVA]

Open /frameworks/base/core/res/res/values/arrays.xml

[SMALI]/[JAVA]

Replace the whole array <array name="lockscreen_targets_with_camera"> .. </array> with:

<array name="lockscreen_targets_with_camera">
<item>@drawable/ic_lockscreen_unlock</item>
<item>@drawable/ic_lockscreen_sms</item>
<item>@drawable/ic_action_assist_generic</item>
<item>@drawable/ic_lockscreen_phone</item>
<item>@drawable/ic_lockscreen_camera</item>
<item>@null</item>
<item>@null</item>
<item>@null</item>
</array>

Replace the whole array <array name="lockscreen_target_descriptions_with_camera"> .. </array> with:

<array name="lockscreen_target_descriptions_with_camera">
<item>@string/description_target_unlock</item>
<item>@string/description_target_sms</item>
<item>@string/description_target_search</item>
<item>@string/description_target_phone</item>
<item>@string/description_target_camera</item>
<item>@null</item>
<item>@null</item>
<item>@null</item>
</array>

[SMALI]

Open /res/values-land/arrays.xml

[JAVA]

Open /frameworks/base/core/res/res/values-land/arrays.xml

[SMALI]/[JAVA]

Replace the whole array <array name="lockscreen_targets_with_camera"> .. </array> with:

<array name="lockscreen_targets_with_camera">
<item>@null</item>
<item>@null</item>
<item>@drawable/ic_lockscreen_unlock</item>
<item>@drawable/ic_lockscreen_sms</item>
<item>@drawable/ic_action_assist_generic</item>
<item>@drawable/ic_lockscreen_phone</item>
<item>@drawable/ic_lockscreen_camera</item>
<item>@null</item>
</array>

Replace the whole array <array name="lockscreen_target_descriptions_with_camera"> .. </array> with:

<array name="lockscreen_target_descriptions_with_camera">
<item>@null</item>
<item>@null</item>
<item>@string/description_target_unlock</item>
<item>@string/description_target_sms</item>
<item>@string/description_target_search</item>
<item>@string/description_target_phone</item>
<item>@string/description_target_camera</item>
<item>@null</item>
</array>

[SMALI]

Open /res/values/strings.xml

[JAVA]

Open /frameworks/base/core/res/res/values/strings.xml

[SMALI]/[JAVA]

Add the following entries:

<string name="description_target_sms">Sms</string>
<string name="description_target_phone">Phone</string>

[SMALI]

Recompile your framework. Then decompile the new one and write down the addresses of the following resources in /res/values/pubblic.xml:

ic_action_assist_generic
ic_lockscreen_camera
ic_lockscreen_silent
ic_lockscreen_unlock
ic_lockscreen_unlock_phantom
ic_lockscreen_phone
ic_lockscreen_sms

framework editing: ***UPDATED***

[JAVA]

Edit /frameworks/base/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java

- return mTargetDescriptions.get(index);
+ String targetZ = "";
+ try {
+ targetZ = mTargetDescriptions.get(index);
+ } catch (Exception e) {
+ }
+ return targetZ;

- return mDirectionDescriptions.get(index);
+ try {
+ String directionZ = mDirectionDescriptions.get(index);
+ return directionZ;
+ } catch (Exception e) {
+ return "";
+ }

[SMALI]

Disassemble your framework.jar

Edit /com/android/internal/widget/multiwaveview/GlowPadView.smali and replace the whole methods ".method private getDirectionDescription(I)Ljava/lang/String;" and ".method private getTargetDescription(I)Ljava/lang/String;" with the following methods:

.method private getDirectionDescription(I)Ljava/lang/String;
.locals 4
.parameter "index"

.prologue
.line 1119
iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mDirectionDescriptions:Ljava/util/ArrayList;

if-eqz v2, :cond_0

iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mDirectionDescriptions:Ljava/util/ArrayList;

invoke-virtual {v2}, Ljava/util/ArrayList;->isEmpty()Z

move-result v2

if-eqz v2, :cond_1

.line 1120
:cond_0
iget v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mDirectionDescriptionsResourceId:I

invoke-direct {p0, v2}, Lcom/android/internal/widget/multiwaveview/GlowPadView;->loadDescriptions(I)Ljava/util/ArrayList;

move-result-object v2

iput-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mDirectionDescriptions:Ljava/util/ArrayList;

.line 1121
iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDrawables:Ljava/util/ArrayList;

invoke-virtual {v2}, Ljava/util/ArrayList;->size()I

move-result v2

iget-object v3, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mDirectionDescriptions:Ljava/util/ArrayList;

invoke-virtual {v3}, Ljava/util/ArrayList;->size()I

move-result v3

if-eq v2, v3, :cond_1

.line 1122
const-string v2, "GlowPadView"

const-string v3, "The number of target drawables must be equal to the number of direction descriptions."

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

.line 1124
const/4 v0, 0x0

.line 1133
:goto_0
return-object v0

.line 1130
:cond_1
:try_start_0
iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mDirectionDescriptions:Ljava/util/ArrayList;

invoke-virtual {v2, p1}, Ljava/util/ArrayList;->get(I)Ljava/lang/Object;

move-result-object v0

check-cast v0, Ljava/lang/String;
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

.line 1131
.local v0, directionZ:Ljava/lang/String;
goto :goto_0

.line 1132
.end local v0 #directionZ:Ljava/lang/String;
:catch_0
move-exception v1

.line 1133
.local v1, e:Ljava/lang/Exception;
const-string v0, ""

goto :goto_0
.end method

.method private getTargetDescription(I)Ljava/lang/String;
.locals 4
.parameter "index"

.prologue
.line 1099
iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDescriptions:Ljava/util/ArrayList;

if-eqz v2, :cond_0

iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDescriptions:Ljava/util/ArrayList;

invoke-virtual {v2}, Ljava/util/ArrayList;->isEmpty()Z

move-result v2

if-eqz v2, :cond_1

.line 1100
:cond_0
iget v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDescriptionsResourceId:I

invoke-direct {p0, v2}, Lcom/android/internal/widget/multiwaveview/GlowPadView;->loadDescriptions(I)Ljava/util/ArrayList;

move-result-object v2

iput-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDescriptions:Ljava/util/ArrayList;

.line 1101
iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDrawables:Ljava/util/ArrayList;

invoke-virtual {v2}, Ljava/util/ArrayList;->size()I

move-result v2

iget-object v3, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDescriptions:Ljava/util/ArrayList;

invoke-virtual {v3}, Ljava/util/ArrayList;->size()I

move-result v3

if-eq v2, v3, :cond_1

.line 1102
const-string v2, "GlowPadView"

const-string v3, "The number of target drawables must be equal to the number of target descriptions."

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

.line 1104
const/4 v1, 0x0

.line 1114
:goto_0
return-object v1

.line 1109
:cond_1
const-string v1, ""

.line 1111
.local v1, targetZ:Ljava/lang/String;
:try_start_0
iget-object v2, p0, Lcom/android/internal/widget/multiwaveview/GlowPadView;->mTargetDescriptions:Ljava/util/ArrayList;

invoke-virtual {v2, p1}, Ljava/util/ArrayList;->get(I)Ljava/lang/Object;

move-result-object v2

move-object v0, v2

check-cast v0, Ljava/lang/String;

move-object v1, v0
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

goto :goto_0

.line 1112
:catch_0
move-exception v2

goto :goto_0
.end method

Recompile your framework.jar

Now we're done with the framework, now we need to modify last file: android.policy.jar

android policy editing:

[JAVA]

Open /frameworks/base/policy/src/com/android/internal/policy/impl/LockScreen.java

Inside the method onTrigger, inside the switch (resId) add:

case com.android.internal.R.drawable.ic_lockscreen_phone:
Intent phoneIntent = new Intent(Intent.ACTION_MAIN);
phoneIntent.setClassName("com.android.contacts", "com.android.contacts.activities.DialtactsActivity");
phoneIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(phoneIntent);
mCallback.goToUnlockScreen();
break;

case com.android.internal.R.drawable.ic_lockscreen_sms:
Intent mmsIntent = new Intent(Intent.ACTION_MAIN);
mmsIntent.setClassName("com.android.mms", "com.android.mms.ui.ConversationList");
mmsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(mmsIntent);
mCallback.goToUnlockScreen();
break;

You're done, feel free to compile!

Of course you can use whatever activity you want, remember to change the images accordingly.

[SMALI]

Disassemble your android.policy.jar

Edit /com/android/internal/policy/impl/LockScreen.smali and add the following methods:

.method static synthetic access$1400(Lcom/android/internal/policy/impl/LockScreen;)Landroid/content/Context;
.locals 1
.parameter "x0"

.prologue
.line 56
iget-object v0, p0, Lcom/android/internal/policy/impl/LockScreen;->mContext:Landroid/content/Context;

return-object v0
.end method

.method static synthetic access$1500(Lcom/android/internal/policy/impl/LockScreen;)Landroid/content/Context;
.locals 1
.parameter "x0"

.prologue
.line 56
iget-object v0, p0, Lcom/android/internal/policy/impl/LockScreen;->mContext:Landroid/content/Context;

return-object v0
.end method

Edit /com/android/internal/policy/impl/LockScreen$GlowPadViewMethods.smali.

Replace the whole method onTrigger with:

.method public onTrigger(Landroid/view/View;I)V
.locals 7
.parameter "v"
.parameter "target"

.prologue
const/high16 v6, 0x1000

.line 313
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->mGlowPadView:Lcom/android/internal/widget/multiwaveview/GlowPadView;

invoke-virtual {v4, p2}, Lcom/android/internal/widget/multiwaveview/GlowPadView;->getResourceIdForTarget(I)I

move-result v3

.line 321
.local v3, resId:I
sparse-switch v3, :sswitch_data_0

.line 367
:goto_0
return-void

.line 323
:sswitch_0
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$1200(Lcom/android/internal/policy/impl/LockScreen;)Landroid/content/Context;

move-result-object v4

invoke-static {v4}, Landroid/app/SearchManager;->getAssistIntent(Landroid/content/Context;)Landroid/content/Intent;

move-result-object v0

.line 324
.local v0, assistIntent:Landroid/content/Intent;
if-eqz v0, :cond_0

.line 325
invoke-direct {p0, v0}, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->launchActivity(Landroid/content/Intent;)V

.line 329
:goto_1
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$400(Lcom/android/internal/policy/impl/LockScreen;)Lcom/android/internal/policy/impl/KeyguardScreenCallback;

move-result-object v4

invoke-interface {v4}, Lcom/android/internal/policy/impl/KeyguardScreenCallback;->pokeWakelock()V

goto :goto_0

.line 327
:cond_0
const-string v4, "LockScreen"

const-string v5, "Failed to get intent for assist activity"

invoke-static {v4, v5}, Landroid/util/Log;->w(Ljava/lang/String;Ljava/lang/String;)I

goto :goto_1

.line 333
.end local v0 #assistIntent:Landroid/content/Intent;
:sswitch_1
new-instance v4, Landroid/content/Intent;

const-string v5, "android.media.action.STILL_IMAGE_CAMERA"

invoke-direct {v4, v5}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V

invoke-direct {p0, v4}, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->launchActivity(Landroid/content/Intent;)V

.line 334
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$400(Lcom/android/internal/policy/impl/LockScreen;)Lcom/android/internal/policy/impl/KeyguardScreenCallback;

move-result-object v4

invoke-interface {v4}, Lcom/android/internal/policy/impl/KeyguardScreenCallback;->pokeWakelock()V

goto :goto_0

.line 339
:sswitch_2
new-instance v2, Landroid/content/Intent;

const-string v4, "android.intent.action.MAIN"

invoke-direct {v2, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V

.line 340
.local v2, phoneIntent:Landroid/content/Intent;
const-string v4, "com.android.contacts"

const-string v5, "com.android.contacts.activities.DialtactsActivity"

invoke-virtual {v2, v4, v5}, Landroid/content/Intent;->setClassName(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

.line 341
invoke-virtual {v2, v6}, Landroid/content/Intent;->setFlags(I)Landroid/content/Intent;

.line 342
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$1300(Lcom/android/internal/policy/impl/LockScreen;)Landroid/content/Context;

move-result-object v4

invoke-virtual {v4, v2}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V

.line 343
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$400(Lcom/android/internal/policy/impl/LockScreen;)Lcom/android/internal/policy/impl/KeyguardScreenCallback;

move-result-object v4

invoke-interface {v4}, Lcom/android/internal/policy/impl/KeyguardScreenCallback;->goToUnlockScreen()V

goto :goto_0

.line 348
.end local v2 #phoneIntent:Landroid/content/Intent;
:sswitch_3
new-instance v1, Landroid/content/Intent;

const-string v4, "android.intent.action.MAIN"

invoke-direct {v1, v4}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V

.line 349
.local v1, mmsIntent:Landroid/content/Intent;
const-string v4, "com.android.mms"

const-string v5, "com.android.mms.ui.ConversationList"

invoke-virtual {v1, v4, v5}, Landroid/content/Intent;->setClassName(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;

.line 350
invoke-virtual {v1, v6}, Landroid/content/Intent;->setFlags(I)Landroid/content/Intent;

.line 351
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$1400(Lcom/android/internal/policy/impl/LockScreen;)Landroid/content/Context;

move-result-object v4

invoke-virtual {v4, v1}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V

.line 352
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$400(Lcom/android/internal/policy/impl/LockScreen;)Lcom/android/internal/policy/impl/KeyguardScreenCallback;

move-result-object v4

invoke-interface {v4}, Lcom/android/internal/policy/impl/KeyguardScreenCallback;->goToUnlockScreen()V

goto :goto_0

.line 357
.end local v1 #mmsIntent:Landroid/content/Intent;
:sswitch_4
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$500(Lcom/android/internal/policy/impl/LockScreen;)V

.line 358
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$400(Lcom/android/internal/policy/impl/LockScreen;)Lcom/android/internal/policy/impl/KeyguardScreenCallback;

move-result-object v4

invoke-interface {v4}, Lcom/android/internal/policy/impl/KeyguardScreenCallback;->pokeWakelock()V

goto/16 :goto_0

.line 364
:sswitch_5
iget-object v4, p0, Lcom/android/internal/policy/impl/LockScreen$GlowPadViewMethods;->this$0:Lcom/android/internal/policy/impl/LockScreen;

invoke-static {v4}, Lcom/android/internal/policy/impl/LockScreen;->access$400(Lcom/android/internal/policy/impl/LockScreen;)Lcom/android/internal/policy/impl/KeyguardScreenCallback;

move-result-object v4

invoke-interface {v4}, Lcom/android/internal/policy/impl/KeyguardScreenCallback;->goToUnlockScreen()V

goto/16 :goto_0

.line 321
:sswitch_data_0
.sparse-switch
0x1080294 -> :sswitch_0
0x10802dd -> :sswitch_1
0x10802f6 -> :sswitch_4
0x10802fe -> :sswitch_5
0x1080301 -> :sswitch_5
0x1080604 -> :sswitch_2
0x1080607 -> :sswitch_3
.end sparse-switch
.end method

Replace the values you wrote down back here:

0x1080294 -> :sswitch_0
0x10802dd -> :sswitch_1
0x10802f6 -> :sswitch_4
0x10802fe -> :sswitch_5
0x1080301 -> :sswitch_5
0x1080604 -> :sswitch_2
0x1080607 -> :sswitch_3

Recompile and you're good to go!

Enjoy and happy editing!