Building The Android Open Source Project – Part 2 – Start Off Small

I want to make a change that is generic to all Android builds so we can ignore (for now) any device specific changes.

 

The change I want to make is to add extra options to the ‘Power Menu’. This is the menu that shows up when you hold down the power button on your device, usually to turn it off. On pure Android devices like the Nexus range, this menu only contains one option ‘Power off’. I want to add some extra options such as an option to reboot your device, toggle airplane mode and put your phone on silent. The functionality for for the airplane mode toggle and silent are already in the code, we’re simply going to expose them; The reboot option is something we will implement ourselves.

 

The change is pretty simple and is all under the folder frameworks/base which you’ll be spending a lot of time in. All paths mentioned below assume you are in this folder.

 

First things first, let’s configure our menu. Go to core/res/res/values/config.xml and find the string-array called ‘config_globalActionsList’. Here we are going to add our new options.

 

Add the following items to the string array:

 

<item>reboot</item>
<item>airplane</item>
<item>silent</item>

 

Next, open the file core/res/res/values/strings.xml and find the string named ‘global_action_power_off’. We’re going to add a new string below here called ‘global_action_reboot’. You’ll notice that global actions already exist for the other two functions if you look down the code a little from here. So add:

 

<string name="global_action_reboot">Reboot</string>

 

This is simply the string that will be shown in the ‘Power Menu’.

 

Now we need to update core/res/res/values/symbols.xml so that we can reference our newly created string from the framework code.

 

Find the ‘global_action_power_off’ java-symbol and add a similar line below it:

 

<java-symbol type="string" name="global_action_reboot"/>

 

Now for the last and most interesting step. We’re going to implement the functionality for our reboot option.

 

Open up services/core/java/com/android/server/policy/GlobalActions.java:

 

First we need to add a new import to make our changes compile successfully, so at the top with all the other imports, add:

 

import android.os.*;

 

Then head down the code to around line 85 and you will see a comment saying that we have some variables that are valid settings for the global actions key. Here is where we need to add a string object for our new reboot action. So below the GLOBAL_ACTION_KEY_POWER add:

 

private static final String GLOBAL_ACTION_KEY_REBOOT = "reboot";

 

Notice that this matches the string we defined back in our first step and the ‘r’ is not capatilized.

 

Further down the class around line 257 you will see an ArraySet being declared called ‘addedKeys’. Right below this there is a for loop which sets up handlers for each type of action declared in the defaultActions string array above. Here is where we’re going to tell the system to handle our new reboot action. So as usual, right below the if statement for GLOBAL_ACTION_KEY_POWER, we want to add an else if statement for our GLOBAL_ACTION_KEY_REBOOT action like so:

 

if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
    mItems.add(new PowerAction());
} else if (GLOBAL_ACTION_KEY_REBOOT.equals(actionKey)) {
    mItems.add(new RebootAction());
}

 

You’ll notice that we have instantiated a new instance of the RebootAction class which doesn’t exist yet; Our next and final step is to create this class.

 

Find the PowerAction class declaration around line 325 and make some space below it to declare our new class as follows:

 

private final class RebootAction extends SinglePressAction {

    private RebootAction(){
        super(R.drawable.ic_lock_power_off, R.string.global_action_power_off);
    }

    @Override
    public void onPress() {
        try {
            IPowerManager powerManager = IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
            powerManager.reboot(false, null, false);
        }catch(RemoteException e){
            Log.e(TAG,&quot;PowerManager service failed! : &quot; +e);
        }
    }

    @Override
    public boolean showDuringKeyguard() {
        return true;
    }

    @Override
    public boolean showBeforeProvisioning() {
        return true;
    }
}

 

So in our constructor we are calling the SinglePressAction constructor that we inherit by extending the SinglePressAction class which gave us our onPress(), showDuringKeyguard() and showBeforeProvisioning() methods that we need to implement. For now we have gone with the default of return true for showDuringKeyguard() and showBeforeProvisioning(). The onPress() method is where the real work is done.

 

Using the PowerAction class as an example, we get a reference to the IPowerManager interface and call the reboot method. The reboot method is defined as follows:

 

void reboot(boolean confirm, String reason, boolean wait);

 

I personally don’t want a confirmation dialog to popup when I hit reboot, so I pass in false for the first parameter; I don’t really want to give a reason for why this is being called so I pass in null for the second parameter, and lastly if we pass true in for the ‘wait’ parameter, the call will wait for the operation to complete and not return, this doesn’t really matter either way to us so i’m just going to pass in false.

 

And that’s it. Go back to the top level directory and run your build command (for me it is ‘make -j5’).
N.B d3m0li5h3r rightly pointed out that you can reduce your build time here to minutes by going to frameworks/base and running ‘mm’ to build everything below that directory only. Then going to your root directory and running ‘make snod’ (system no update). This is a huge time saver so I highly recommend doing this.

 

This time around I have the benefit of the CCACHE we setup in part 1 and also the make tool is intelligent enough to not have to rebuild everything so it took around 30 mins (with the make -j5 method, the make snod method should take minutes) to build again with my updates.
Advertisements

6 thoughts on “Building The Android Open Source Project – Part 2 – Start Off Small”

  1. Just yesterday I was searching for how to add reboot to power options. Thanks for the article. But 1 thing I noticed in the article was that when you made changes to incorporate reboot, you are again running
    make -j5
    Now instead of this you can run
    mmm frameworks/base
    from android-source root dir and then
    make snod
    to exponentially reduce the build time.
    mmm should not take more than 2 mins and make snod will take another 2-5 mins. You will save ample amount of time next time onwards.

    Like

      1. I think it should be ‘mm’ as this builds all the modules in the current directory. ‘mmm’ takes directories as an argument to build. I’ll update the guide, thanks!

        Like

  2. I might be having issues rendering your code snippets… I’m getting a bunch of “&lt” and “&gt”. I’m guessing they’re angle brackets.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s