Android 7.1 navigation bar adds keys, shutdown menu adds sleep option

Posted by faswad on Tue, 15 Oct 2019 19:14:55 +0200

platform

rk3288 + Android 7.1

Requirement specification

1. Add the power button in the navigation bar and click it to open the shutdown menu.
2. Add sleep item in shutdown menu item and click backward sleep

Related documents

//modify
	modified:   frameworks/base/core/java/android/view/WindowManagerPolicy.java
	modified:   frameworks/base/core/res/res/values/config.xml
	modified:   frameworks/base/core/res/res/values/strings.xml
	modified:   frameworks/base/core/res/res/values/symbols.xml
	modified:   frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
	modified:   frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
	modified:   frameworks/base/packages/SystemUI/res/values/config.xml
	modified:   frameworks/base/packages/SystemUI/res/values/strings.xml
	modified:   frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
	modified:   frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
	modified:   frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
	modified:   frameworks/base/services/core/java/com/android/server/policy/GlobalActions.java
	modified:   frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
	modified:   frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

//Newly added
	frameworks/base/core/res/res/drawable/ic_sleep.xml
	frameworks/base/packages/SystemUI/res/drawable-nodpi/ic_sysbar_power.png
	frameworks/base/packages/SystemUI/res/layout/power.xml

Realization

Navigation bar add key

Prepare the corresponding icon and related characters:
frameworks/base/packages/SystemUI/res/drawable-nodpi/ic_sysbar_power.png
|-- frameworks/base/packages/SystemUI/res/values/strings.xml

<string name="accessibility_power" translatable="false">Power</string>

Add key layout.
|-- frameworks/base/packages/SystemUI/res/layout/power.xml

<com.android.systemui.statusbar.policy.KeyButtonView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/power"
    android:layout_width="@dimen/navigation_key_width"
    android:layout_height="match_parent"
    android:layout_weight="0"
    android:src="@drawable/ic_sysbar_power"
    systemui:keyCode="0"
    android:scaleType="center"
    android:contentDescription="@string/accessibility_power"
    android:paddingStart="@dimen/navigation_key_padding"
    android:paddingEnd="@dimen/navigation_key_padding"
    />

Where, keyCode is the key value. If you do not want to process it as a key, set it to 0.

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java

	public static final String POWER = "power";
//Load button
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        inflateChildren();
        clearViews();
        inflateLayout(getDefaultLayout());
    }
//Default button
    protected String getDefaultLayout() {
        return mContext.getString(R.string.config_navBarLayout);
    }

    protected void inflateLayout(String newLayout) {
        mCurrentLayout = newLayout;
        if (newLayout == null) {
            newLayout = getDefaultLayout();
        }
        String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);
        String[] start = sets[0].split(BUTTON_SEPARATOR);
        String[] center = sets[1].split(BUTTON_SEPARATOR);
        String[] end = sets[2].split(BUTTON_SEPARATOR);
        // Inflate these in start to end order or accessibility traversal will be messed up.
        inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
        inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
        LinearLayout centerLayout = (LinearLayout)mRot0.findViewById(R.id.center_group);
        mIsReverseInflateRot0 = !isRot0Landscape && !isSw600Dp() && mCurrentOrientation == Configuration.ORIENTATION_LANDSCAPE;
        if(mIsReverseInflateRot0)
            centerLayout.setOrientation(LinearLayout.VERTICAL);
        inflateButtons(center, centerLayout, isRot0Landscape);
        mIsReverseInflateRot0 = false;
        centerLayout = (LinearLayout)mRot90.findViewById(R.id.center_group);
        mIsReverseInflateRot90 = !isRot0Landscape && !isSw600Dp() && mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT;
        if(mIsReverseInflateRot90)
            centerLayout.setOrientation(LinearLayout.HORIZONTAL);
        inflateButtons(center, centerLayout, !isRot0Landscape);
        mIsReverseInflateRot90 = false;
        addGravitySpacer((LinearLayout) mRot0.findViewById(R.id.ends_group));
        addGravitySpacer((LinearLayout) mRot90.findViewById(R.id.ends_group));

        inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group), isRot0Landscape);
        inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group), !isRot0Landscape);
    }

//Add navigation bar
    @Nullable
    protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
        LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
        float size = extractSize(buttonSpec);
        String button = extractButton(buttonSpec);
        View v = null;
        if (HOME.equals(button)) {
            v = inflater.inflate(R.layout.home, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (BACK.equals(button)) {
            v = inflater.inflate(R.layout.back, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (RECENT.equals(button)) {
            v = inflater.inflate(R.layout.recent_apps, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (SCREENSHOT.equals(button)) {
            v = inflater.inflate(R.layout.screenshot, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
//Add the POWER button below. layout.power.xml is also used here
        }else if (POWER.equals(button)) {
            v = inflater.inflate(R.layout.power, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (VOLUME_ADD.equals(button)) {
            v = inflater.inflate(R.layout.volume_add, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (VOLUME_SUB.equals(button)) {
            v = inflater.inflate(R.layout.volume_sub, parent, false);
            if (landscape && isSw600Dp()) {
                setupLandButton(v);
            }
        } else if (MENU_IME.equals(button)) {
            v = inflater.inflate(R.layout.menu_ime, parent, false);
        } else if (NAVSPACE.equals(button)) {
            v = inflater.inflate(R.layout.nav_key_space, parent, false);
        } else if (CLIPBOARD.equals(button)) {
            v = inflater.inflate(R.layout.clipboard, parent, false);
        } else if (button.startsWith(KEY)) {
            String uri = extractImage(button);
            int code = extractKeycode(button);
            v = inflater.inflate(R.layout.custom_key, parent, false);
            ((KeyButtonView) v).setCode(code);
            if (uri != null) {
                ((KeyButtonView) v).loadAsync(uri);
            }
        } else {
            return null;
        }

        if (size != 0) {
            ViewGroup.LayoutParams params = v.getLayoutParams();
            params.width = (int) (params.width * size);
        }
        if(mIsReverseInflateRot0 || mIsReverseInflateRot90){
            setupVerticalButton(v);
        }

        parent.addView(v);
        addToDispatchers(v);

        View lastView = landscape ? mLastLandscape : mLastPortrait;
        if (lastView != null) {
            v.setAccessibilityTraversalAfter(lastView.getId());
        }
        if (landscape) {
            mLastLandscape = v;
        } else {
            mLastPortrait = v;
        }
        return v;
    }

The default key layout is defined as "config" navbarlayout:

	frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java:        return mContext.getString(R.string.config_navBarLayout);
	frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java:            navLayout = context.getString(R.string.config_navBarLayout);
	frameworks/base/packages/SystemUI/res/values/config.xml:    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
	frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml:    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
	frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml:    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>

Add power's individual changes:

diff --git a/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml b/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
old mode 100644
new mode 100755
index aa03ab2..ef41fee
--- a/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/frameworks/base/packages/SystemUI/res/values-sw600dp/config.xml
@@ -34,7 +34,7 @@
     <bool name="config_keyguardUserSwitcher">true</bool>
 
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot,power;menu_ime</string>
 
     <!-- Animation duration when using long press on recents to dock -->
     <integer name="long_press_dock_anim_duration">290</integer>
diff --git a/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml b/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
old mode 100644
new mode 100755
index 016f7e5..c992349
--- a/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
+++ b/frameworks/base/packages/SystemUI/res/values-sw900dp/config.xml
@@ -19,6 +19,6 @@
 <resources>
 
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot,power;menu_ime</string>
 
 </resources>
diff --git a/frameworks/base/packages/SystemUI/res/values/config.xml b/frameworks/base/packages/SystemUI/res/values/config.xml
old mode 100644
new mode 100755
index da5f4bf..59e7161
--- a/frameworks/base/packages/SystemUI/res/values/config.xml
+++ b/frameworks/base/packages/SystemUI/res/values/config.xml
@@ -280,7 +280,7 @@
     <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>
 
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot;menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">space;volume_sub,back,home,recent,volume_add,screenshot,power;menu_ime</string>
 
     <bool name="quick_settings_show_full_alarm">false</bool>

The add touch event setting button is visible:
|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

//Click to process:
	private View.OnClickListener mPowerClickListener = new View.OnClickListener(){
		public void onClick(View v){
			Intent intent = new Intent("android.intent.action.POWER_MENU");
			mContext.sendBroadcast(intent);
		}
	};
	private void prepareNavigationBarView() {
        mNavigationBarView.reorient();

        ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
        recentsButton.setOnClickListener(mRecentsClickListener);
        recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
        recentsButton.setLongClickable(true);
        recentsButton.setOnLongClickListener(this::handleLongPressBackRecents);

        ButtonDispatcher backButton = mNavigationBarView.getBackButton();
        backButton.setLongClickable(true);
        backButton.setOnLongClickListener(this::handleLongPressBackRecents);

        ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
        homeButton.setOnTouchListener(mHomeActionListener);
        homeButton.setOnLongClickListener(mLongPressHomeListener);
 
        ButtonDispatcher screenshotButton=mNavigationBarView.getScreenshotButton();
        screenshotButton.setOnClickListener(mScreenshotClickListener);
        screenshotButton.setOnTouchListener(mScreenshotTouchListener);
        screenshotButton.setVisibility(View.VISIBLE);
        boolean isShow=Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREENSHOT_BUTTON_SHOW, 1)==1;
        if(isShow){
            screenshotButton.setVisibility(View.VISIBLE);
        }else{
            screenshotButton.setVisibility(View.GONE);
        }

//Add monitor and use key to see.
		ButtonDispatcher powerButton=mNavigationBarView.getPowerButton();
        powerButton.setOnClickListener(mPowerClickListener);
        //powerButton.setOnTouchListener(mPowerTouchListener);
        powerButton.setVisibility(View.VISIBLE);
		...
	}

|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java

    public NavigationBarView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mDisplay = ((WindowManager) context.getSystemService(
                Context.WINDOW_SERVICE)).getDefaultDisplay();

        mVertical = false;
        mShowMenu = false;
        mGestureHelper = new NavigationBarGestureHelper(context);

        mConfiguration = new Configuration();
        mConfiguration.updateFrom(context.getResources().getConfiguration());
        updateIcons(context, Configuration.EMPTY, mConfiguration);

        mBarTransitions = new NavigationBarTransitions(this);

        mButtonDisatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
        mButtonDisatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
        mButtonDisatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
        mButtonDisatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
        mButtonDisatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
        mButtonDisatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot));
//Add to collection.
        mButtonDisatchers.put(R.id.power, new ButtonDispatcher(R.id.power));
        mButtonDisatchers.put(R.id.volume_add, new ButtonDispatcher(R.id.volume_add));
        mButtonDisatchers.put(R.id.volume_sub, new ButtonDispatcher(R.id.volume_sub));
    }

//For external calls
    public ButtonDispatcher getPowerButton() {
        return mButtonDisatchers.get(R.id.power);
    }

At this point, the key is added. After clicking, the broadcast android.intent.action.power menu will be sent.

Design sketch:

Add sleep item in shutdown menu

Prepare resources:
frameworks/base/core/res/res/drawable/ic_sleep.xml
|-- frameworks/base/core/res/res/values/strings.xml

diff --git a/frameworks/base/core/res/res/values/strings.xml b/frameworks/base/core/res/res/values/strings.xml
old mode 100644
new mode 100755
index 4172864..89d45d7
--- a/frameworks/base/core/res/res/values/strings.xml
+++ b/frameworks/base/core/res/res/values/strings.xml
@@ -496,6 +496,9 @@
 
     <!-- label for item that turns off power in phone options dialog -->
     <string name="global_action_power_off">Power off</string>
+       
+       <string name="global_action_sleep">Sleep</string>
 
     <!-- label for item that restarts phone in phone options dialog -->
     <!-- TODO: promote to separate string-->

frameworks/base/core/res/res/values/symbols.xml

diff --git a/frameworks/base/core/res/res/values/symbols.xml b/frameworks/base/core/res/res/values/symbols.xml
old mode 100644
new mode 100755
index 81d06af..02815a2
--- a/frameworks/base/core/res/res/values/symbols.xml
+++ b/frameworks/base/core/res/res/values/symbols.xml
@@ -1607,6 +1607,7 @@
   <java-symbol type="string" name="faceunlock_multiple_failures" />
   <java-symbol type="string" name="global_action_power_off" />
   <java-symbol type="string" name="global_action_restart" />
+  <java-symbol type="string" name="global_action_sleep" />
   <java-symbol type="string" name="global_actions_airplane_mode_off_status" />
   <java-symbol type="string" name="global_actions_airplane_mode_on_status" />
   <java-symbol type="string" name="global_actions_toggle_airplane_mode" />
@@ -2734,6 +2735,7 @@
   <java-symbol type="array" name="config_defaultFirstUserRestrictions" />
 
   <java-symbol type="drawable" name="ic_restart" />
+  <java-symbol type="drawable" name="ic_sleep" />

frameworks/base/core/res/res/values/config.xml

diff --git a/frameworks/base/core/res/res/values/config.xml b/frameworks/base/core/res/res/values/config.xml
old mode 100644
new mode 100755
index e4839d7..935110a
--- a/frameworks/base/core/res/res/values/config.xml
+++ b/frameworks/base/core/res/res/values/config.xml
@@ -2209,6 +2209,7 @@
     <string-array translatable="false" name="config_globalActionsList">
         <item>power</item>
         <item>restart</item>
+               <item>sleep</item>
         <item>bugreport</item>
         <item>users</item>
     </string-array>

Delete build intermediate file:
rm -rf out/target/product/rk3288/system/framework/framework-res.apk out/target/product/rk3288/obj/APPS/framework-res_intermediates out/target/product/rk3288/obj/NOTICE_FILES/src/system/framework/framework-res.apk.txt out/target/product/rk3288/obj/PACKAGING/target_files_intermediates/rk3288-target_files-eng.anson/SYSTEM/framework/framework-res.apk out/target/common/obj/APPS/framework-res_intermediates
Recompile
mmm frameworks/base/core/res/ -j4

Add sleep interface
|-- frameworks/base/core/java/android/view/WindowManagerPolicy.java

    public interface WindowManagerFuncs {
        public static final int LID_ABSENT = -1;
        public static final int LID_CLOSED = 0;
        public static final int LID_OPEN = 1;

        public static final int CAMERA_LENS_COVER_ABSENT = -1;
        public static final int CAMERA_LENS_UNCOVERED = 0;
        public static final int CAMERA_LENS_COVERED = 1;

        /**
         * Ask the window manager to re-evaluate the system UI flags.
         */
        public void reevaluateStatusBarVisibility();

        /**
         * Add a input consumer which will consume all input events going to any window below it.
         */
        public InputConsumer addInputConsumer(Looper looper,
                InputEventReceiver.Factory inputEventReceiverFactory);

        /**
         * Returns a code that describes the current state of the lid switch.
         */
        public int getLidState();

        /**
         * Lock the device now.
         */
        public void lockDeviceNow();

        /**
         * Returns a code that descripbes whether the camera lens is covered or not.
         */
        public int getCameraLensCoverState();

        /**
         * Switch the input method, to be precise, input method subtype.
         *
         * @param forwardDirection {@code true} to rotate in a forward direction.
         */
        public void switchInputMethod(boolean forwardDirection);

        public void shutdown(boolean confirm);
        public void reboot(boolean confirm);
        public void rebootSafeMode(boolean confirm);
//increase
		public void sleep();
	}

Implementation of sleep:
|-- frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
	...
    // Called by window manager policy.  Not exposed externally.
    @Override
    public void shutdown(boolean confirm) {
        ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
    }

    // Called by window manager policy.  Not exposed externally.
    @Override
    public void reboot(boolean confirm) {
        ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
    }

    // Called by window manager policy.  Not exposed externally.
    @Override
    public void rebootSafeMode(boolean confirm) {
        ShutdownThread.rebootSafeMode(mContext, confirm);
    }

//Implement sleep, call PowerManager.goToSleep.
	@Override
	public void sleep(){
		mPowerManager.goToSleep(SystemClock.uptimeMillis());
	}
	...
}

Add sleep item
|-- frameworks/base/services/core/java/com/android/server/policy/GlobalActions.java

    private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
//Increase sleep
	private static final String GLOBAL_ACTION_KEY_SLEEP = "sleep";

    private GlobalActionsDialog createDialog() {
		...
//Load config ﹣ globalactionslist character array from xml
        mItems = new ArrayList<Action>();
        String[] defaultActions = mContext.getResources().getStringArray(
                com.android.internal.R.array.config_globalActionsList);

        ArraySet<String> addedKeys = new ArraySet<String>();
        for (int i = 0; i < defaultActions.length; i++) {
            String actionKey = defaultActions[i];
            if (addedKeys.contains(actionKey)) {
                // If we already have added this, don't add it again.
                continue;
            }
            if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
                mItems.add(new PowerAction());
            } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
                mItems.add(mAirplaneModeOn);
            } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
                if (Settings.Global.getInt(mContext.getContentResolver(),
                        Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
                    mItems.add(new BugReportAction());
                }
            } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {
                if (mShowSilentToggle) {
                    mItems.add(mSilentModeAction);
                }
            } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {
                if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
                    addUsersToMenu(mItems);
                }
            } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
                mItems.add(getSettingsAction());
            } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
                mItems.add(getLockdownAction());
            } else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
                mItems.add(getVoiceAssistAction());
            } else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
                mItems.add(getAssistAction());
            } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
                mItems.add(new RestartAction());

//Create and add a SleepAction
			} else if (GLOBAL_ACTION_KEY_SLEEP.equals(actionKey)){
				mItems.add(new SleepAction());
            } else {
                Log.e(TAG, "Invalid global action key " + actionKey);
            }
            // Add here so we don't add more than one.
            addedKeys.add(actionKey);
        }

        if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
            mItems.add(getEmergencyAction());
        }

        mAdapter = new MyAdapter();

        AlertParams params = new AlertParams(mContext);
        params.mAdapter = mAdapter;
		...
	}


//Add SleepAction.
	private final class SleepAction extends SinglePressAction implements LongPressAction {
        private SleepAction() {
            super(R.drawable.ic_sleep, R.string.global_action_sleep);
        }

        @Override
        public boolean onLongPress() {
            return false;
        }

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

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

        @Override
        public void onPress() {
//Call the new sleep function
            mWindowManagerFuncs.sleep();
        }
    }

Receive broadcast from system UI and call up GlobalActions.
|-- frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    /** {@inheritDoc} */
    @Override
    public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs) {
        mContext = context;
        mWindowManager = windowManager;
        mWindowManagerFuncs = windowManagerFuncs;
		...
        // register for dream-related broadcasts
        filter = new IntentFilter();
        filter.addAction(Intent.ACTION_DREAMING_STARTED);
        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
        context.registerReceiver(mDreamReceiver, filter);

        filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SHUTDOWN);
        context.registerReceiver(mShutdownanimationReceiver, filter);

        // register for multiuser-relevant broadcasts
        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
        context.registerReceiver(mMultiuserReceiver, filter);

//Register broadcast listening: android.intent.action.power menu
		IntentFilter ifPower = new IntentFilter("android.intent.action.POWER_MENU");
		context.registerReceiver(new BroadcastReceiver(){
			@Override
			public void onReceive(Context context, Intent intent) {
				//show global actions dialog
				showGlobalActionsInternal();
			}
		}, ifPower);
	}

Complete, above:

Topics: xml Android Java git