본문 바로가기

안드로이드

[안드로이드]Application 개발 시 Platform key signing이 필요한 경우


*Application 개발 시 Platform key signing이 필요한 경우 
 
일반적인 개발자나 3rd Party 개발사에 제공되는 SDK로 개발되는 apk파일과는 달리 
Vendor에게 제공되는 Internal or hidden API를 사용해서 개발한 Application은 일반적인 Device에 설치해서 실행할 수 없다. (예를 들면, Settings.apk같은 소스 파일을 구해도 실제로 폰에 설치해서 해당 기능을 이용할 수 없음)


이는 시장에 출시된 폰은 Vendor가 User mode 로 build 한 image를 사용하기 때문인데 

User mode로  build하는 경우, Vendor 는 android 에서 제공되는 known key (\build\target\product\security\)가 아닌 각자의 unique 한 key 를 만들어서 signing 한다.



1) Emulator의 경우 
system 권한이 필요한 appilcation 을 emulator 에 설치해서 debugging 하고 싶다면, known key 인 platform key 로 signing 하면 된다. 방법은 다음과 같다. 

\build\target\product\security\ 에서 platform.pk8, platform.x509.pem 파일을 가져온다.


하기 와 같이 순서데로 진행하면, platform.jks 파일이 생성 된다.

==========================================================================================

>openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
>openssl pkcs12 -export -in platform.x509.pem -inkey platform.pem -out platform.p12 -password pass:android -name androiddebugkey

>keytool -importkeystore -deststorepass android -destkeystore platform.jks -srcstoretype PKCS12 -srcstorepass android -srckeystore platform.p12
==========================================================================================
Eclipse - 메뉴 - windows - Preferences - Android - Build - Custom debug keystore 에 생성한 platform.jks 를 선택한다.

clean 후 다시 build 해서 emulator 에 설치하면 잘 돌아간다.

2) Target Device의 경우 
그렇다면, Eclipse 에서 build 후, Emul 이 아닌, 바로 Target 에서 돌리려면 ??
Target 의 system signature 를 맞춰야 한다.

출시 된 User mode device 라면 불가능하다.
개발 단계에서 eng / debug build 된 image 가 flashing 된 device 라면,
Emul 과 동일하게 Android 에서 제공하는 key 로 signing 할 것이므로 위의 Emulator 에 설치하는 것과 동일한 방법으로 설치해서 실행 확인이 가능하다.


개발 단계와 Release 단계의 signing key 가 다르다.

따라서, system 권한이 필요한 Setting 의 경우, Platform key 로 signing 후, 설치되지만, 이미 유저가 가지고 있는 device 의 vendor 측 platform key 를 가지고 있지 않은 이상, 다른 환경에서 build 되거나, 다른 device 에서 가져온 Settings.apk 를 설치하기란 불가능하다.

(설치하려고 하면, INSTALL_FAILED_SHARED_USER_INCOMPATIBLE error 가 뜰 것이다.)


물론, 위에서 언급했듯이 Setting 만의 특정 기능을 뺀다면 가능하다.


Setting 만의 특정 기능이란, 타 application 을 memory 상에서 깨끗하게 kill 할 수 있는 기능이다.


이는 3rd party application 에선 사용이 불 가능하며, system 권한, 자격이 필요하다.


하지만 system 권한, 자격을 포기한다면, platform key 로 signing 할 필요 없으며, 이는 곳 일반적인 application 으로써, 어떤 device 든지 기 설치되어 있는 settings.apk 만 확실히 제거한 후, 설치해서 사용이 가능하다.


이 system 자격, 권한을 포기한다는 의미가, AndroidManifest.xml 에서 속성으로 명시된,

android:sharedUserId="android.uid.system" 항목을 삭제하는 것이다.


system process 와 같은 uid 를 사용하므로써, system process 의 code & data 를 똑 같이 공유할 수 있는 권한을 해당 application 에게 준다는 의미이다.


따라서 위 항목을 지우고 build 한 apk 를 설치하면 아주 자~~알 설치될 것이다.


하지만,~~ Settings > Applications >Manage applications 에서 "Force stop" 버튼을 클릭 하는 순간 unexpected error, 즉 setting application 이 죽을 것이다.


대표적인 internal api method 인, ActivityManager 의 forceStopPackage() 를 예로 들어보자.

System 자격이 있는 넘이 호출해야 할 함수를 setting application 이 호출했기 때문에 permission error 가 나는 것이다.


이 함수를 실행하기 위해서는 permission 이 필요한데, 

<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"></uses-permission>

라고 AndroidManifest.xml 에 명시해줘야 한다.


이렇게 해서 build 된 apk 를 install 한 후, 실행 하면 하기와 같은 exception 이 발생한다.


====================================================================================

07-21 10:38:13.480: WARN/ActivityManager(1981): Permission Denial: forceStopPackage() from pid=3565, uid=10110 requires android.permission.FORCE_STOP_PACKAGES

07-21 10:38:13.503: ERROR/AndroidRuntime(3565): FATAL EXCEPTION: main

07-21 10:38:13.503: ERROR/AndroidRuntime(3565): java.lang.SecurityException: Permission Denial: forceStopPackage() from pid=3565, uid=10110 requires android.permission.FORCE_STOP_PACKAGES

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Parcel.readException(Parcel.java:1260)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Parcel.readException(Parcel.java:1248)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.app.ActivityManagerProxy.forceStopPackage(ActivityManagerNative.java:2564)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.app.ActivityManager.forceStopPackage(ActivityManager.java:968)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.lge.lmk.activities.RunningProcessActivity$4.onClick(RunningProcessActivity.java:850)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:158)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Handler.dispatchMessage(Handler.java:99)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.os.Looper.loop(Looper.java:123)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at android.app.ActivityThread.main(ActivityThread.java:4668)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at java.lang.reflect.Method.invokeNative(Native Method)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at java.lang.reflect.Method.invoke(Method.java:521)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)

07-21 10:38:13.503: ERROR/AndroidRuntime(3565):     at dalvik.system.NativeStart.main(Native Method)

07-21 10:38:13.511: WARN/ActivityManager(1981):   Force finishing activity com.lge.lmk/.activities.LmkMainActivity

====================================================================================

"android.permission.FORCE_STOP_PACKAGES" Permission 을 명시해 줬는데 왜 그럴까?





system process 의 권한이 없기 때문이다.


system process 와 동일한 권한을 갖기위해서는?


AndroidManifest.xml 파일의 manifest attribute 에 하기와 같이 지정해 주면 된다.

android:sharedUserId="android.uid.system"


이 application process 의 uid 를 system 과 공유함으로써, system 과 동일한 권한을 갖겠다는 의미다.


참 편리하게 system 권한을 가질 수 있다고 생각할 수 있지만, 이는 어디까지 platform(system)  과 signature 가 같을 때의 경우에만 해당된다.


아무리 rooting 을 했건, 뭐를 했건간에, User mode 로 빌드 된 image 를 바꿀 순 없다.

모든 사용자가 가지고 있는 폰은 User mode 로 빌드 된 image 가 탑재 되었고, 각 모델별 고유한 platform key 로 signing 되었기 때문에,

(Vendor 측에 아는 사람이 있어 debug 나, engineer 모드로 빌드된 image 를 구할 수 있다면??)

전체 이미지 빌드 타임에 system 과 data 영역에 들어갈 모든 apk 까지 싹 다 각각 명시된 key 값으로 signing 한다.


때문에, Signature 가 Platform과 맞지 않은 Settings application 을 폰에 탑재하는 순간, 아래와 같은 logcat msg 와 함께, 해당 apk 는 launcher 에서 볼 수 없을 것이다.(PackageManager 가 package loading 실패)

===========================================================================================

07-21 10:56:36.007: DEBUG/PackageParser(1981): Scanning package: /system/app/ApplicationManager.apk

07-21 10:56:36.007: INFO/PackageManager(1981): /system/app/ApplicationManager.apk changed; collecting certs

07-21 10:56:36.046: DEBUG/PackageManager(1981): Scanning package com.lge.lmk

07-21 10:56:36.046: DEBUG/PackageManager(1981): Shared UserID android.uid.system (uid=1000): packages=[PackageSetting{464d74d8 de.emsys.usbmode.control/1000}, PackageSetting{462eaed0 com.lge.charging_test/1000}, PackageSetting{46415808 com.google.android.location/1000}, PackageSetting{466c4260 de.emsys.usbmode.service/1000}, PackageSetting{464a8c08 com.lge.hiddenmenu/1000}, PackageSetting{46392e68 com.android.providers.subscribedfeeds/1000}, PackageSetting{4639d108 com.android.server.vpn/1000}, PackageSetting{462b8cd8 com.jungle.app.service/1000}, PackageSetting{4630d8f0 com.lge.internal/1000}, PackageSetting{46353388 com.lge.providers.flex/1000}, PackageSetting{46475660 android/1000}, PackageSetting{46298f28 com.android.settings/1000}, PackageSetting{461ff250 com.android.providers.settings/1000}, PackageSetting{46259770 com.lge.sui.widget/1000}]

07-21 10:56:36.046: WARN/PackageManager(1981): Package com.lge.lmk shared user changed from <nothing> to android.uid.system; replacing with new

07-21 10:56:36.054: WARN/PackageManager(1981): Signature mismatch for shared user : SharedUserSetting{462749e8 android.uid.system/1000}

07-21 10:56:36.054: ERROR/PackageManager(1981): Package com.lge.lmk has no signatures that match those in shared user android.uid.system; ignoring!

===========================================================================================


또는,(아래는 살짝 다른 유형의 error 다.)

===========================================================================================

08-09 09:47:06.046: DEBUG/PackageManager(1973): Scanning package com.lge.lmk

08-09 09:47:06.054: DEBUG/PackageManager(1973): Shared UserID android.uid.system (uid=1000): packages=[PackageSetting{462d48a8 com.android.server.vpn/1000}, PackageSetting{462af928 com.lge.internal/1000}, PackageSetting{462e8908 com.lge.sui.widget/1000}, PackageSetting{462cded0 com.lge.hiddenmenu/1000}, PackageSetting{462cdcb0 de.emsys.usbmode.control/1000}, PackageSetting{462e9ad8 com.google.android.location/1000}, PackageSetting{462af0d0 com.jungle.app.service/1000}, PackageSetting{462b06c0 android/1000}, PackageSetting{462af2d0 de.emsys.usbmode.service/1000}, PackageSetting{462e6cc0 com.android.settings/1000}, PackageSetting{462daad0 com.lge.providers.flex/1000}, PackageSetting{462dc5d8 com.android.providers.settings/1000}, PackageSetting{462e3270 com.android.providers.subscribedfeeds/1000}, PackageSetting{462e5430 com.lge.charging_test/1000}, PackageSetting{462e8c48 com.lge.lmk/1000}]

08-09 09:47:06.054: WARN/PackageManager(1973): Signature mismatch for shared user : SharedUserSetting{4621b8b0 android.uid.system/1000}

08-09 09:47:06.054: WARN/PackageManager(1973): Trying to update system app code path from /system/app/ApplicationManager_signed.apk to /system/app/ApplicationManager.apk

08-09 09:47:06.054: ERROR/PackageManager(1973): Package com.lge.lmk signatures do not match the previously installed version; ignoring!

08-09 09:47:06.257: INFO/IQClient(2030): submitHW03 -  status- 2 level- 74

===========================================================================================


system 쪽과 signature mis-match 가 나서 이 어플을 loading 할 수 없다는 의미이다.


 


방법은 해당 어플도 똑같이 platform signing 을 해줘야 한다.(위에서 언급한 system 권한을 없애는 방법도 있다.)

그래야 system 권한을 얻을 수 있다는 의미이다.


방법은 하기와 같이 platform key를 구해와서 signing 해주면 된다.

Platform key 는 어디서 구할까...??? 해당 모델의 Vendor 만이 알 수 있다.


java -jar signapk.jar platform.x509.pem platform.pk8 Unsigned.apk Signed.apk


Signed.apk 를 설치해주면 모두 정상 동작 된다.

'안드로이드' 카테고리의 다른 글

monkeyrunner  (0) 2011.10.23