Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab089d48 authored by Justin Koh's avatar Justin Koh Committed by Android Git Automerger
Browse files

am 9d4ed1ec: am ddd168d6: Merge "Add global key configuration file" into jb-mr2-dev

* commit '9d4ed1ec':
  Add global key configuration file
parents f0426c6a 9d4ed1ec
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2577,6 +2577,14 @@ public class Intent implements Parcelable, Cloneable {
    public static final String ACTION_SHOW_BRIGHTNESS_DIALOG =
            "android.intent.action.SHOW_BRIGHTNESS_DIALOG";

    /**
     * Broadcast Action:  A global button was pressed.  Includes a single
     * extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
     * caused the broadcast.
     * @hide
     */
    public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";

    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // Standard intent categories (see addCategory()).
+1 −0
Original line number Diff line number Diff line
@@ -1106,6 +1106,7 @@
  <java-symbol type="xml" name="time_zones_by_country" />
  <java-symbol type="xml" name="sms_short_codes" />
  <java-symbol type="xml" name="audio_assets" />
  <java-symbol type="xml" name="global_keys" />

  <java-symbol type="raw" name="accessibility_gestures" />
  <java-symbol type="raw" name="incognito_mode_start_page" />
+31 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2013, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->

<!-- Mapping of keycodes to components which will be handled globally.
     Modify this file to add global keys.
     A global key will NOT go to the foreground application and instead only ever be sent via targeted
     broadcast to the specified component. The action of the intent will be
     android.intent.action.GLOBAL_BUTTON and the KeyEvent will be included in the intent as
     android.intent.extra.KEY_EVENT.
-->

<global_keys version="1">
    <!-- Example format: keyCode = keycode to handle globally. component = component which will handle this key. -->
    <!-- <key keyCode="KEYCODE_VOLUME_UP" component="com.android.example.keys/.VolumeKeyHandler" /> -->
</global_keys>
+126 −0
Original line number Diff line number Diff line
/*
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.policy.impl;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;
import android.view.KeyEvent;

import com.android.internal.util.XmlUtils;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

/**
 * Stores a mapping of global keys.
 * <p>
 * A global key will NOT go to the foreground application and instead only ever be sent via targeted
 * broadcast to the specified component. The action of the intent will be
 * {@link Intent#ACTION_GLOBAL_BUTTON} and the KeyEvent will be included in the intent with
 * {@link Intent#EXTRA_KEY_EVENT}.
 */
final class GlobalKeyManager {

    private static final String TAG = "GlobalKeyManager";

    private static final String TAG_GLOBAL_KEYS = "global_keys";
    private static final String ATTR_VERSION = "version";
    private static final String TAG_KEY = "key";
    private static final String ATTR_KEY_CODE = "keyCode";
    private static final String ATTR_COMPONENT = "component";

    private static final int GLOBAL_KEY_FILE_VERSION = 1;

    private SparseArray<ComponentName> mKeyMapping;

    public GlobalKeyManager(Context context) {
        mKeyMapping = new SparseArray<ComponentName>();
        loadGlobalKeys(context);
    }

    /**
     * Broadcasts an intent if the keycode is part of the global key mapping.
     *
     * @param context context used to broadcast the event
     * @param keyCode keyCode which triggered this function
     * @param event keyEvent which trigged this function
     * @return {@code true} if this was handled
     */
    boolean handleGlobalKey(Context context, int keyCode, KeyEvent event) {
        if (mKeyMapping.size() > 0) {
            ComponentName component = mKeyMapping.get(keyCode);
            if (component != null) {
                Intent intent = new Intent(Intent.ACTION_GLOBAL_BUTTON)
                        .setComponent(component)
                        .putExtra(Intent.EXTRA_KEY_EVENT, event);
                context.sendBroadcastAsUser(intent, UserHandle.CURRENT, null);
                return true;
            }
        }
        return false;
    }

    /**
     * Returns {@code true} if the key will be handled globally.
     */
    boolean shouldHandleGlobalKey(int keyCode, KeyEvent event) {
        return mKeyMapping.get(keyCode) != null;
    }

    private void loadGlobalKeys(Context context) {
        XmlResourceParser parser = null;
        try {
            parser = context.getResources().getXml(com.android.internal.R.xml.global_keys);
            XmlUtils.beginDocument(parser, TAG_GLOBAL_KEYS);
            int version = parser.getAttributeIntValue(null, ATTR_VERSION, 0);
            if (GLOBAL_KEY_FILE_VERSION == version) {
                while (true) {
                    XmlUtils.nextElement(parser);
                    String element = parser.getName();
                    if (element == null) {
                        break;
                    }
                    if (TAG_KEY.equals(element)) {
                        String keyCodeName = parser.getAttributeValue(null, ATTR_KEY_CODE);
                        String componentName = parser.getAttributeValue(null, ATTR_COMPONENT);
                        int keyCode = KeyEvent.keyCodeFromString(keyCodeName);
                        if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
                            mKeyMapping.put(keyCode, ComponentName.unflattenFromString(
                                    componentName));
                        }
                    }
                }
            }
        } catch (Resources.NotFoundException e) {
            Log.w(TAG, "global keys file not found", e);
        } catch (XmlPullParserException e) {
            Log.w(TAG, "XML parser exception reading global keys file", e);
        } catch (IOException e) {
            Log.w(TAG, "I/O exception reading global keys file", e);
        } finally {
            if (parser != null) {
                parser.close();
            }
        }
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -449,6 +449,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    PowerManager.WakeLock mBroadcastWakeLock;
    boolean mHavePendingMediaKeyRepeatWithWakeLock;

    // Maps global key codes to the components that will handle them.
    private GlobalKeyManager mGlobalKeyManager;

    // Fallback actions by key code.
    private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
            new SparseArray<KeyCharacterMap.FallbackAction>();
@@ -902,6 +905,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        mScreenshotChordEnabled = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_enableScreenshotChord);

        mGlobalKeyManager = new GlobalKeyManager(mContext);

        // Controls rotation and the like.
        initializeHdmiState();

@@ -2208,6 +2213,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            return -1;
        }

        if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
            return -1;
        }

        // Let the application handle the key.
        return 0;
    }
@@ -3653,6 +3662,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            }
        }

        // If the key would be handled globally, just return the result, don't worry about special
        // key processing.
        if (mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
            return result;
        }

        // Handle special keys.
        switch (keyCode) {
            case KeyEvent.KEYCODE_VOLUME_DOWN: