[Sprint LG Optimus G] BMP7777:
Porting an AOSP based ROM (MIUI, COS, CM, etc):

Special thanks to AdhvanIt for putting this together for everyone!

For this project, you'll need to get familiar with adb, apktool, and meld. Since these already have tutorials, I'll link those instead of writing my own for each.

COMPREHENSIVE GUIDE TO ADB | LEARN TO LOGCAT LIKE A PRO | APKTOOL | MELD

The most successful ports to the LGOG will come from Nexus 4 based ROMs, as they are the most similar in chipset to our device. For this guide, we will reference base ROM as the build from our device, and reference port as the ROM you'll be bringing to our device.

Getting started:

Extract your base ROM into a working folder of your choice. Inside, you'll find:

[COLOR="Black"]System - The majority of the work we'll do will be in here.
Data - May contain applications, boot scripts, config files etc.
META-INF - Contains certificates and signature for signcheck and updater-script, update-binary (updater-script command processor)
boot.img - Kernel/ramdisk packed together. This should only be touched in the event you wish to use a kernel that is separate from the one in your base ROM, or to edit the ramdisk.[/COLOR]

From inside your working folder, you'll want to delete the following directories and all files contained within them:

[COLOR="black"]/system/app
/system/fonts
/system/framework
/system/media[/COLOR]

Open your port archive and extract those same folders into /system directory of your working folder.

Some ports such as MIUI, cos, etc also require that certain permissions xml's (inside /system/etc/permissions) be copied over so that the theme engines will work properly.

Modifying build.prop:

[COLOR="black"]In your additional build properties section, you'll find lines similar to this.
ro.config.ringtone=
ro.config.notification_sound=
ro.config.alarm_alert=
ro.config.sms_received_sound=
ro.config.sms_delivered_sound=[/COLOR]

They contain ringtones that are in the base ROM, and will need to be changed to those in the port.

This is the base work for porting a ROM. From here, you'll want to zip and sign the ROM, then attempt to boot (Note: it will not boot yet).

Framework mods required for the device to boot:

Navigate to /system/framework and decompile the following:

[COLOR="black"]framework-res.apk
framework.jar
telephony-common.jar[/COLOR]

Note: some ports may require services.jar and android.policy.jar decompiled as well, but no other framework will change in a port as they are common among all AOSP ROMs.

Extract and decompile the same frameworks from your base ROM zip.

The following is a list of the exact methods/classes and framework xml's that need replaced or modified to port COS from the N4 to the LGOG. Some of these will be universal between different ports, and some will be specific to COS. When you run into issues, you'll want to take a look at the steps for debugging below.

framework-res.apk:

/res/values/arrays.xml:

[COLOR="black"]<array name="config_cdma_dun_supported_types" />
Change this line to:
<string-array name="config_cdma_dun_supported_types">
<item>default</item>
<item>dun</item>
<item>mms</item>
<item>supl</item>
</string-array>[/COLOR]

res/values/bools.xml:

[COLOR="black"] <bool name="config_telephony_use_own_number_for_voicemail">false</bool>
<bool name="config_mms_content_disposition_support">true</bool>
<bool name="config_showNavigationBar">true</bool>[/COLOR]

Change to:

[COLOR="black"] <bool name="config_telephony_use_own_number_for_voicemail">true</bool>
<bool name="config_mms_content_disposition_support">false</bool>
<bool name="config_showNavigationBar">false</bool>[/COLOR]

res/xml/eri.xml:

Replace this xml with the one from your base ROM.

telephony-common.jar:

com/android/internal/telephony:

For this, you'll want to replace entire smali trees with those from your base ROM. First, the RIL smali tree, or RIL*.smali:

[COLOR="black"]RIL.smali
RIL$1.smali
RIL$RILReceiver.smali
RIL$RILSender.smali
RILRequest.smali[/COLOR]

Also:

[COLOR="black"]LGEQualcommCDMARIL*.smali
PhoneFactory.smali[/COLOR]

framework.jar

android/content/res/AssetManager.smali:

Change:

[COLOR="black"].field private static final sSync:Ljava/lang/Object;
.field static sSystem:Landroid/content/res/AssetManager;

# instance fields
.field private mNObject:I

.field private mNumRefs:I[/COLOR]

To:

[COLOR="black"].field private static final sSync:Ljava/lang/Object;

.field static sSystem:Landroid/content/res/AssetManager;

# instance fields
.field private mAppName:Ljava/lang/String;

.field private mAssetDir:Ljava/lang/String;

.field private mNObject:I

.field private mNumRefs:I[/COLOR]

Change:

[COLOR="black"].field private mOpen:Z

.field private mRefStacks:Ljava/util/HashMap;
.annotation system Ldalvik/annotation/Signature;[/COLOR]

To:

[COLOR="black"].field private mOpen:Z

.field private mRedirections:Landroid/util/SparseArray;
.annotation system Ldalvik/annotation/Signature;
value = {
"Landroid/util/SparseArray",
"<",
"Landroid/content/res/PackageRedirectionMap;",
">;"
}
.end annotation
.end field

.field private mRefStacks:Ljava/util/HashMap;
.annotation system Ldalvik/annotation/Signature;
Change:
Code:
.field private mStringBlocks:[Landroid/content/res/StringBlock;

.field private final mValue:Landroid/util/TypedValue;

# direct methods[/COLOR]

To:

[COLOR="black"].field private mStringBlocks:[Landroid/content/res/StringBlock;

.field private mThemeCookie:I

.field private mThemePackageName:Ljava/lang/String;

.field private mThemeSupport:Z

.field private final mValue:Landroid/util/TypedValue;

# direct methods[/COLOR]

Change:

[COLOR="black"].end method

.method static final native applyStyle(IIII[I[I[I)Z
.end method

.method static final native applyThemeStyle(IIZ)V
.end method

.method static final native copyTheme(II)V
.end method[/COLOR]

To:

[COLOR="black"].end method

.method private final native addRedirectionsNative(I)V
.end method

.method static final native applyStyle(IIII[I[I[I)Z
.end method

.method static final native applyThemeStyle(IIZ)V
.end method

.method private final native clearRedirectionsNative()V
.end method

.method static final native copyTheme(II)V
.end method[/COLOR]

Change:

[COLOR="black"].method private final native seekAsset(IJI)J
.end method

# virtual methods
.method public final native addAssetPath(Ljava/lang/String;)I
To:
Code:
.end method

.method private final native splitThemePackage(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)I
.end method

# virtual methods
.method public final native addAssetPath(Ljava/lang/String;)I[/COLOR]

Change:

[COLOR="black"] invoke-virtual {p0, v2}, Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I

move-result v2

aput v2, v0, v1

.line 620
add-int/lit8 v1, v1, 0x1

goto :goto_0
.end method

.method public close()V
.locals 1[/COLOR]

To:

[COLOR="black"] invoke-virtual {p0, v2}, Landroid/content/res/AssetManager;->addAssetPath(Ljava/lang/String;)I

move-result v2

aput v2, v0, v1

.line 620
add-int/lit8 v1, v1, 0x1

goto :goto_0
.end method

.method public addRedirections(Landroid/content/res/PackageRedirectionMap;)V
.locals 2
.parameter "map"

.prologue
.line 747
iget-object v0, p0, Landroid/content/res/AssetManager;->mRedirections:Landroid/util/SparseArray;

if-nez v0, :cond_0

.line 748
new-instance v0, Landroid/util/SparseArray;

const/4 v1, 0x2

invoke-direct {v0, v1}, Landroid/util/SparseArray;-><init>(I)V

iput-object v0, p0, Landroid/content/res/AssetManager;->mRedirections:Landroid/util/SparseArray;

.line 750
:cond_0
iget-object v0, p0, Landroid/content/res/AssetManager;->mRedirections:Landroid/util/SparseArray;

invoke-virtual {p1}, Landroid/content/res/PackageRedirectionMap;->getPackageId()I

move-result v1

invoke-virtual {v0, v1, p1}, Landroid/util/SparseArray;->append(ILjava/lang/Object;)V

.line 751
invoke-virtual {p1}, Landroid/content/res/PackageRedirectionMap;->getNativePointer()I

move-result v0

invoke-direct {p0, v0}, Landroid/content/res/AssetManager;->addRedirectionsNative(I)V

.line 752
return-void
.end method

.method public final native attachThemePath(Ljava/lang/String;)I
.end method

.method public clearRedirections()V
.locals 1

.prologue
.line 759
iget-object v0, p0, Landroid/content/res/AssetManager;->mRedirections:Landroid/util/SparseArray;

if-eqz v0, :cond_0

.line 760
iget-object v0, p0, Landroid/content/res/AssetManager;->mRedirections:Landroid/util/SparseArray;

invoke-virtual {v0}, Landroid/util/SparseArray;->clear()V

.line 762
:cond_0
invoke-direct {p0}, Landroid/content/res/AssetManager;->clearRedirectionsNative()V

.line 763
return-void
.end method

.method public close()V
.locals 1[/COLOR]

Change:

[COLOR="black"].end method

.method final ensureStringBlocks()V
To:
Code:
.end method

.method public final native detachThemePath(Ljava/lang/String;I)Z
.end method

.method final ensureStringBlocks()V
Change:
Code:
.end method

.method final native getArrayIntResource(I)[I
.end method

.method final native getArraySize(I)I
.end method

.method public final native getCookieName(I)Ljava/lang/String;[/COLOR]

To:

[COLOR="black"].end method

.method public final native generateStyleRedirections(III)Z
.end method

.method final native getArrayIntResource(I)[I
.end method

.method final native getArraySize(I)I
.end method

.method public final native getBasePackageCount()I
.end method

.method public final native getBasePackageId(I)I
.end method

.method public final native getBasePackageName(I)Ljava/lang/String;
.end method

.method public final native getCookieName(I)Ljava/lang/String;
Change:
Code:
.end method

.method final getThemeValue(IILandroid/util/TypedValue;Z)Z
[/COLOR]

To:

[COLOR="black"].end method

.method public getThemeCookie()I
.locals 1

.prologue
.line 730
iget v0, p0, Landroid/content/res/AssetManager;->mThemeCookie:I

return v0
.end method

.method public getThemePackageName()Ljava/lang/String;
.locals 1

.prologue
.line 714
iget-object v0, p0, Landroid/content/res/AssetManager;->mThemePackageName:Ljava/lang/String;

return-object v0
.end method

.method final getThemeValue(IILandroid/util/TypedValue;Z)Z[/COLOR]

Change:

[COLOR="black"].end method

.method public final native isUpToDate()Z
To:
Code:
.end method

.method public final hasThemeSupport()Z
.locals 1

.prologue
.line 696
iget-boolean v0, p0, Landroid/content/res/AssetManager;->mThemeSupport:Z

return v0
.end method

.method public final native isUpToDate()Z[/COLOR]

Change:

[COLOR="black"].end method

.method final releaseTheme(I)V[/COLOR]

To:

[COLOR="black"].end method

.method final recreateStringBlocks()V
.locals 1

.prologue
.line 272
monitor-enter p0

.line 273
const/4 v0, 0x1

:try_start_0
invoke-virtual {p0, v0}, Landroid/content/res/AssetManager;->makeStringBlocks(Z)V

.line 274
monitor-exit p0

.line 275
return-void

.line 274
:catchall_0
move-exception v0

monitor-exit p0
:try_end_0
.catchall {:try_start_0 .. :try_end_0} :catchall_0

throw v0
.end method

.method final releaseTheme(I)V[/COLOR]

Change:

[COLOR="black"].method public final native setLocale(Ljava/lang/String;)V
.end method

.method xmlBlockGone(I)V[/COLOR]

To:

[COLOR="black"].method public final native setLocale(Ljava/lang/String;)V
.end method

.method public setThemeCookie(I)V
.locals 0
.parameter "cookie"

.prologue
.line 738
iput p1, p0, Landroid/content/res/AssetManager;->mThemeCookie:I

.line 739
return-void
.end method

.method public setThemePackageName(Ljava/lang/String;)V
.locals 0
.parameter "packageName"

.prologue
.line 722
iput-object p1, p0, Landroid/content/res/AssetManager;->mThemePackageName:Ljava/lang/String;

.line 723
return-void
.end method

.method public final setThemeSupport(Z)V
.locals 0
.parameter "themeSupport"

.prologue
.line 686
iput-boolean p1, p0, Landroid/content/res/AssetManager;->mThemeSupport:Z

.line 687
return-void
.end method

.method public final splitDrmProtectedThemePackage(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)I
.locals 1
.parameter "packageFileName"
.parameter "lockedFileName"
.parameter "drmProtectedresources"

.prologue
.line 492
invoke-direct {p0, p1, p2, p3}, Landroid/content/res/AssetManager;->splitThemePackage(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)I

move-result v0

return v0
.end method

.method xmlBlockGone(I)V[/COLOR]

Replace the following smali files with the ones from your base:

[COLOR="black"]android/content/res/PackageRedirectionMap*.smali
android/hardware/Camera*.smali
android/telephony/TelephonyManager.smali
android/webkit/HTML5*.smali
android/webkit/WebSettingsClassic.smali
Change:
Code:
.field private mWebGLEnabled:Z

.field private mWebView:Landroid/webkit/WebViewClassic;[/COLOR]

To:

[COLOR="black"].field private mWebGLEnabled:Z

.field private mWebSocketsEnabled:Z

.field private mWebView:Landroid/webkit/WebViewClassic;[/COLOR]

Change:

[COLOR="black"] .line 93
iput-boolean v3, p0, Landroid/webkit/WebSettingsClassic;->mDomStorageEnabled:Z

.line 94[/COLOR]

To:

[COLOR="black"] .line 93
iput-boolean v3, p0, Landroid/webkit/WebSettingsClassic;->mWebSocketsEnabled:Z

iput-boolean v3, p0, Landroid/webkit/WebSettingsClassic;->mDomStorageEnabled:Z

.line 94[/COLOR]

Change:

[COLOR="black"] monitor-exit p0

throw v2
.end method

.method isNarrowColumnLayout()Z[/COLOR]

To:

[COLOR="black"]monitor-exit p0

throw v2
.end method

.method public declared-synchronized getWebSocketsEnabled()Z
.locals 1

.prologue
.line 1342
monitor-enter p0

:try_start_0
iget-boolean v0, p0, Landroid/webkit/WebSettingsClassic;->mWebSocketsEnabled:Z
:try_end_0
.catchall {:try_start_0 .. :try_end_0} :catchall_0

monitor-exit p0

return v0

:catchall_0
move-exception v0

monitor-exit p0

throw v0
.end method

.method isNarrowColumnLayout()Z[/COLOR]

Debugging:

Legend:

[COLOR="Black"]"E/" - Error
"E/dalvikvm"- Crucial system error
"No such file or directory" - Should be self-eplanatory.
"fail"/"failed" - Crucial error
"W/"/"warning" - Self explanatory.
"exception"(especially NullPointerException) - Points to something that was done incorrectly during the port.[/COLOR]

Common error types:

Couldn't find native method:

[COLOR="black"]method static synthetic access$100(Landroid/hardware/Camera;)
E/dalvikvm( 100): ERROR: couldn't find native method
E/dalvikvm( 100): Requested: Landroid/hardware/Camera;.Camera$PictureCallback;
E/JNIHelp ( 100): RegisterNatives failed for 'Landroid/hardware/Camera', aborting[/COLOR]

This will help us figure out where the issue is:

[COLOR="black"]E/JNIHelp ( 100): RegisterNatives failed for 'Landroid/hardware/Camera'[/COLOR]

>>

[COLOR="black"]android/hardware/Camera[/COLOR]

The smali we're looking for is Camera.smali. Finding the path does require a little knowledge of source code structure. But in this case, we can assume that any path starting with "android" points to framework.jar

You'll want to take the single missing method from base smali and put it in the corresponding port smali. In this case, .Camera$PictureCallback. In some cases, you can get away with using entire smali files (or smali trees consisting of all smali files starting with the same name) from your base ROM in your port. Though this can cause issues if you get carried away.

Fatal signal 11:

[COLOR="black"]F/libc ( 2698): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1)
I/DEBUG ( 130): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 130): Build fingerprint: 'google/occam/mako:4.2.2/JDQ39/573038:user/release-keys'
I/DEBUG ( 130): pid: 2698, tid: 2698 >>> zygote <<<
I/DEBUG ( 130): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
I/DEBUG ( 130): r0 deadbaad r1 00000001 r2 a0000000 r3 00000000
I/DEBUG ( 130): r4 00000000 r5 00000027 r6 4086fbfd r7 00000036
I/DEBUG ( 130): r8 40253f04 r9 40233a7e 10 0000904c fp 00009062
I/DEBUG ( 130): ip 4028b240 sp befcfa60 lr 401043c1 pc 40100adc cpsr 600
00030
I/DEBUG ( 130): d0 2f64696f72646e61 d1 2f746e65746e6f63
I/DEBUG ( 130): d2 657373412f736572 d3 726567616e614d74
I/DEBUG ( 130): d4 0000d4cc0000d4b1 d5 0000d4e80000d4cd[/COLOR]

When you see a code block like the start of that one, look just above it. You'll find the error that caused it up a few lines.

Unable to extract+optimize DEX from '/system/framework/framework.jar' and other errors:

[COLOR="black"]D/dalvikvm( 103): DexOpt: --- BEGIN 'framework.jar' (bootstrap=1) ---
E/dalvikvm( 172): Duplicate class definition: 'Landroid/media/MediaRecorder;'
E/dalvikvm( 172): Trouble with item 2900 @ offset 0x17a86c
E/dalvikvm( 172): Cross-item verify of section type 0006 failed
E/dalvikvm( 172): ERROR: Byte swap + verify failed
E/dalvikvm( 172): Optimization failed
W/dalvikvm( 103): DexOpt: --- END 'framework.jar' --- status=0xff00, process failed
E/dalvikvm( 103): Unable to extract+optimize DEX from '/system/framework/framework.jar'
D/dalvikvm( 103): Unable to process classpath element '/system/framework/framework.jar'
E/JNIHelp ( 103): Native registration unable to find class 'android/debug/JNITest', aborting[/COLOR]

[COLOR="black"]E/NetworkLocationRealOs(2304): no android ID; can't access encrypted cache
E/NetworkLocationRealOs(2304): java.io.IOException: no android ID; can't access encrypted cache[/COLOR]

[COLOR="black"]E/System(1538): java.lang.NullPointerException
E/System(1538): at com.android.server.pm.PackageManagerService.grantPermissionsLPw(PackageManagerService.java:4299)
E/System(1538): at com.android.server.pm.PackageManagerService.updatePermissionsLPw(PackageManagerService.java:4247)
E/System(1538): at com.android.server.pm.PackageManagerService.<init>(PackageManagerService.java:1170)
E/System(1538): at com.android.server.pm.PackageManagerService.main(PackageManagerService.java:858)
E/System(1538): at com.android.server.ServerThread.run(SystemServer.java:167)
I/SystemServer(1538): Input Method Service
W/SystemServer(1538): ***********************************************
A/SystemServer(1538): BOOT FAILURE starting Input Manager Service
A/SystemServer(1538): java.lang.NullPointerException
A/SystemServer(1538): at android.app.PendingIntent.getBroadcast(PendingIntent.java:293)
A/SystemServer(1538): at com.android.server.InputMethodManagerService.<init>(InputMethodManagerService.java:548)
at com.android.server.ServerThread.run(SystemServer.java:271)
Error reporting WTF
E/AndroidRuntime(1538): java.lang.NullPointerException
E/AndroidRuntime(1538): at com.android.internal.os.RuntimeInit.wtf(RuntimeInit.java:345)
E/AndroidRuntime(1538): at android.util.Log$1.onTerribleFailure(Log.java:103)
E/AndroidRuntime(1538): at android.util.Log.wtf(Log.java:278)
E/AndroidRuntime(1538): at com.android.server.ServerThread.reportWtf(SystemServer.java:77)
E/AndroidRuntime(1538): at com.android.server.ServerThread.run(SystemServer.java:274)[/COLOR]

The errors above are typically tied to issues with your build. Either framework that's been decompiled/compiled improperly, or the classes that you've diffed.

The methods above can be found in your base AssetManager.smali. I've provided exactly what you need to replace so that you can do it with as little trial and error as necessary. If you make a mistake in AssetManager, even your logcat won't give you any usable information...

​