We need to test our newly added method. Therefore, we make use of the PacktLibraryClient
application that we created in the Writing the platform library source code recipe.
Open up Client.java
from the PacktLibraryClient
application, which is located at ANDROID_SRC/packages/apps/PacktLibraryClient/src/com/packtclient/
.
The following code represents the client code that makes use of the newly added method and is saved in a file named
Client.java
:package com.packtclient; import packt.platformlibrary.PacktPlatformLibrary; import android.app.Activity; import android.app.ActivityManager; import android.os.Bundle; import android.util.Log; public class Client extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //byte [] encr = PacktPlatformLibrary.encryptDES("password", "Packt"); //PacktPlatformLibrary.printHex(encr); invokeNewPacktAMSMethod(); } void invokeNewPacktAMSMethod() { ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); int val = am.packtSensitiveMethod(2); Log.i("CustomAMS", "return: " + val); } }
I have just commented the earlier code and added a method to execute
packtSensitiveMethod
.Now, run a full system make and start the emulator.
Note
Sometimes, the emulator may complain that the partition size is too small and it has to be resized. In this case, you can use the memory and partition size switches. (Note that this command will work only if you issue it in the same window in which Android was built. Otherwise, you will have to use the fully qualified paths and specify the full paths to the emulator images—kernel image, system image as well.)
For example, emulator memory as 512 and partition-size as 1024.
Launch the
PacktLibraryClient
application. Observe logcat. The output will be similar to the following:I/ActivityManager( 63): Start proc com.packtclient for activity com.packtclient/.Client: pid=344 uid=10010 gids={} I/dalvikvm( 63): Jit: resizing JitTable from 512 to 1024 I/ARMAssembler( 63): generated scanline__00000177:03515104_00001002_00000000 [ 87 ipp] (110 ins) at [0x4386b6f0:0x4386b8a8] in 1311254 ns D/AndroidRuntime( 344): Shutting down VM W/dalvikvm( 344): threadid=1: thread exiting with uncaught exception (group=0x40015560) E/AndroidRuntime( 344): FATAL EXCEPTION: main E/AndroidRuntime( 344): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.packtclient/com.packtclient.Client}: java.lang.SecurityException: Requires permission packt.PACKT_PERMISSION E/AndroidRuntime( 344): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647) E/AndroidRuntime( 344): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663) E/AndroidRuntime( 344): at android.app.ActivityThread.access$1500(ActivityThread.java:117) E/AndroidRuntime( 344): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) E/AndroidRuntime( 344): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 344): at android.os.Looper.loop(Looper.java:130) E/AndroidRuntime( 344): at android.app.ActivityThread.main(ActivityThread.java:3683) E/AndroidRuntime( 344): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 344): at java.lang.reflect.Method.invoke(Method.java:507) E/AndroidRuntime( 344): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) E/AndroidRuntime( 344): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) E/AndroidRuntime( 344): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime( 344): Caused by: java.lang.SecurityException: Requires permission packt.PACKT_PERMISSION E/AndroidRuntime( 344): at android.os.Parcel.readException(Parcel.java:1322) E/AndroidRuntime( 344): at android.os.Parcel.readException(Parcel.java:1276) E/AndroidRuntime( 344): at android.app.ActivityManagerProxy.packtSensitiveMethod(ActivityManagerNative.java:2918) E/AndroidRuntime( 344): at android.app.ActivityManager.packtSensitiveMethod(ActivityManager.java:1077) E/AndroidRuntime( 344): at com.packtclient.Client.invokeNewPacktAMSMethod(Client.java:28) E/AndroidRuntime( 344): at com.packtclient.Client.onCreate(Client.java:22) E/AndroidRuntime( 344): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) E/AndroidRuntime( 344): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611) E/AndroidRuntime( 344): ... 11 more W/ActivityManager( 63): Force finishing activity com.packtclient/.Client
What went wrong here? On analyzing the logs, we notice that a security exception was thrown. So, our code works! The sensitive method is protected. But, if
PacktLibraryClient
is a legitimate application and needs access topacktSensitiveMethod
, we need to do two things:Grant it
PACKT_PERMISSION
.Sign the APK with the platform certificate since the permission is a signature level permission.
To do this, edit the
AndroidManifest.xml
file ofPacktLibraryClient
by adding the following tag outside theapplication
tag:<uses-permission android:name="packt.PACKT_PERMISSION" />
Next, edit its
Android.mk
file by adding the following line:LOCAL_CERTIFICATE := platform
Now we will use a shortcut to quickly build the APK. In a terminal, navigate to the root of your android sources and use the following command:
mmm packages/apps/PacktLibraryClient
This will build the APK, but won't place it into the system image or push it into the emulator. To do this, we will remount the system partition as read/write and then push it manually. If you want to place it into the system image directly and have it rerun the emulator, use the following command:
mmm packages/apps/PacktLibraryClient snod
If you closed the emulator, start it again. Then drop into a shell via
adb
.To find out on which block device
/system
is mounted, use:cat /proc/mtd
The output looks like:
dev: size erasesize name mtd0: 3e100000 00020000 "system" mtd1: 3e100000 00020000 "userdata" mtd2: 04000000 00020000 "cache"
Hence,
/system
ismtd0
.To remount as read/write:
mount -o rw,remount -t yaffs2 /dev/block/mtd0 /system chmod 777 /system/app
Now exit the
adb
shell, and push the built APK. The APK will be available atANDROID_SRC/out/target/product/generic/system/app
.The following command will automatically reinstall the APK onto the emulator. Start the application again and observe the logs.
adb push PacktLibraryClient.apk /system/app I/PACKTinAMS( 68): sensitive method called with parameter: 2 I/CustomAMS( 372): return: 4
We see that everything has worked fine.
The application obtains a reference to the Activity Manager service. This reference is in the form of an ActivityManager
object. The packtSensitiveMethod
shim is executed in the client, which cause an RPC to be sent out to the Activity Manager service, which performs a permission check before executing the main body of the method. When our APK wasn't signed with the platform key and didn't include the correct <uses-permission>
tag, this check failed and the application crashed. In the second instance, we made the appropriate changes and the permission check succeeded.