Using the custom method (Should know)

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.

Getting ready

Open up Client.java from the PacktLibraryClient application, which is located at ANDROID_SRC/packages/apps/PacktLibraryClient/src/com/packtclient/.

How to do it...

  1. 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.

  2. 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.

  3. 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 to packtSensitiveMethod, 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.
      1. To do this, edit the AndroidManifest.xml file of PacktLibraryClient by adding the following tag outside the application tag:
        <uses-permission android:name="packt.PACKT_PERMISSION" />
      2. Next, edit its Android.mk file by adding the following line:
        LOCAL_CERTIFICATE := platform
        
      3. 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
        
      4. 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
        
      5. If you closed the emulator, start it again. Then drop into a shell via adb.
      6. 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 is mtd0.

      7. To remount as read/write:
        mount -o rw,remount -t yaffs2 /dev/block/mtd0 /system
        chmod 777 /system/app
        
      8. Now exit the adb shell, and push the built APK. The APK will be available at ANDROID_SRC/out/target/product/generic/system/app.
      9. 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.

How it works...

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.222.12