summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/globalactions/Action.java42
-rw-r--r--core/java/com/android/internal/globalactions/ActionsAdapter.java112
-rw-r--r--core/java/com/android/internal/globalactions/ActionsDialog.java94
-rw-r--r--core/java/com/android/internal/globalactions/LongPressAction.java21
-rw-r--r--core/java/com/android/internal/globalactions/SinglePressAction.java99
-rw-r--r--core/java/com/android/internal/globalactions/ToggleAction.java155
-rw-r--r--services/core/java/com/android/server/policy/GlobalActions.java35
-rw-r--r--services/core/java/com/android/server/policy/GlobalActionsProvider.java46
-rw-r--r--services/core/java/com/android/server/policy/LegacyGlobalActions.java495
-rw-r--r--services/core/java/com/android/server/policy/PowerAction.java61
-rw-r--r--services/core/java/com/android/server/policy/RestartAction.java60
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java23
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java49
13 files changed, 755 insertions, 537 deletions
diff --git a/core/java/com/android/internal/globalactions/Action.java b/core/java/com/android/internal/globalactions/Action.java
new file mode 100644
index 000000000000..ddb75c1cb11b
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/Action.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/** What each item in the global actions dialog must be able to support. */
+public interface Action {
+ /** @return Text that will be announced when dialog is created. {@code null} for none. */
+ CharSequence getLabelForAccessibility(Context context);
+
+ /** Create the view that represents this action. */
+ View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater);
+
+ /** Called when the action is selected by the user. */
+ void onPress();
+
+ /** @return whether this action should appear in the dialog when the keygaurd is showing. */
+ boolean showDuringKeyguard();
+
+ /** @return whether this action should appear in the dialog before the device is provisioned. */
+ boolean showBeforeProvisioning();
+
+ /** @return {@code true} if the action is enabled for user interaction. */
+ boolean isEnabled();
+}
diff --git a/core/java/com/android/internal/globalactions/ActionsAdapter.java b/core/java/com/android/internal/globalactions/ActionsAdapter.java
new file mode 100644
index 000000000000..c9f01ce9c08b
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/ActionsAdapter.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import java.util.function.BooleanSupplier;
+import java.util.List;
+
+/**
+ * The adapter used for the list within the global actions dialog, taking into account whether the
+ * keyguard is showing via {@link LegacyGlobalActions#mKeyguardShowing} and whether the device is
+ * provisioned via {@link LegacyGlobalActions#mDeviceProvisioned}.
+ */
+public class ActionsAdapter extends BaseAdapter {
+ private final Context mContext;
+ private final List<Action> mItems;
+ private final BooleanSupplier mDeviceProvisioned;
+ private final BooleanSupplier mKeyguardShowing;
+
+ public ActionsAdapter(Context context, List<Action> items,
+ BooleanSupplier deviceProvisioned, BooleanSupplier keyguardShowing) {
+ mContext = context;
+ mItems = items;
+ mDeviceProvisioned = deviceProvisioned;
+ mKeyguardShowing = keyguardShowing;
+ }
+
+ @Override
+ public int getCount() {
+ final boolean keyguardShowing = mKeyguardShowing.getAsBoolean();
+ final boolean deviceProvisioned = mDeviceProvisioned.getAsBoolean();
+ int count = 0;
+
+ for (int i = 0; i < mItems.size(); i++) {
+ final Action action = mItems.get(i);
+
+ if (keyguardShowing && !action.showDuringKeyguard()) {
+ continue;
+ }
+ if (!deviceProvisioned && !action.showBeforeProvisioning()) {
+ continue;
+ }
+ count++;
+ }
+ return count;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return getItem(position).isEnabled();
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return false;
+ }
+
+ @Override
+ public Action getItem(int position) {
+ final boolean keyguardShowing = mKeyguardShowing.getAsBoolean();
+ final boolean deviceProvisioned = mDeviceProvisioned.getAsBoolean();
+
+ int filteredPos = 0;
+ for (int i = 0; i < mItems.size(); i++) {
+ final Action action = mItems.get(i);
+ if (keyguardShowing && !action.showDuringKeyguard()) {
+ continue;
+ }
+ if (!deviceProvisioned && !action.showBeforeProvisioning()) {
+ continue;
+ }
+ if (filteredPos == position) {
+ return action;
+ }
+ filteredPos++;
+ }
+
+ throw new IllegalArgumentException("position " + position
+ + " out of range of showable actions"
+ + ", filtered count=" + getCount()
+ + ", keyguardshowing=" + keyguardShowing
+ + ", provisioned=" + deviceProvisioned);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ Action action = getItem(position);
+ return action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
+ }
+}
diff --git a/core/java/com/android/internal/globalactions/ActionsDialog.java b/core/java/com/android/internal/globalactions/ActionsDialog.java
new file mode 100644
index 000000000000..1cca1cc64ca1
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/ActionsDialog.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.internal.globalactions;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.KeyEvent;
+import android.widget.ListView;
+import com.android.internal.app.AlertController;
+
+/** A dialog that lists the given Action items to be user selectable. */
+public final class ActionsDialog extends Dialog implements DialogInterface {
+ private final Context mContext;
+ private final AlertController mAlert;
+ private final ActionsAdapter mAdapter;
+
+ public ActionsDialog(Context context, AlertController.AlertParams params) {
+ super(context, getDialogTheme(context));
+ mContext = getContext();
+ mAlert = AlertController.create(mContext, this, getWindow());
+ mAdapter = (ActionsAdapter) params.mAdapter;
+ params.apply(mAlert);
+ }
+
+ private static int getDialogTheme(Context context) {
+ TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
+ outValue, true);
+ return outValue.resourceId;
+ }
+
+ @Override
+ protected void onStart() {
+ super.setCanceledOnTouchOutside(true);
+ super.onStart();
+ }
+
+ public ListView getListView() {
+ return mAlert.getListView();
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mAlert.installContent();
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ for (int i = 0; i < mAdapter.getCount(); ++i) {
+ CharSequence label =
+ mAdapter.getItem(i).getLabelForAccessibility(getContext());
+ if (label != null) {
+ event.getText().add(label);
+ }
+ }
+ }
+ return super.dispatchPopulateAccessibilityEvent(event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (mAlert.onKeyDown(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mAlert.onKeyUp(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+}
diff --git a/core/java/com/android/internal/globalactions/LongPressAction.java b/core/java/com/android/internal/globalactions/LongPressAction.java
new file mode 100644
index 000000000000..eed4cd9fe9b3
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/LongPressAction.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.internal.globalactions;
+
+/** An action that also supports long press. */
+public interface LongPressAction extends Action {
+ boolean onLongPress();
+}
diff --git a/core/java/com/android/internal/globalactions/SinglePressAction.java b/core/java/com/android/internal/globalactions/SinglePressAction.java
new file mode 100644
index 000000000000..0b8cd0b2c266
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/SinglePressAction.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/** A single press action maintains no state, just responds to a press and takes an action. */
+public abstract class SinglePressAction implements Action {
+ private final int mIconResId;
+ private final Drawable mIcon;
+ private final int mMessageResId;
+ private final CharSequence mMessage;
+
+ protected SinglePressAction(int iconResId, int messageResId) {
+ mIconResId = iconResId;
+ mMessageResId = messageResId;
+ mMessage = null;
+ mIcon = null;
+ }
+
+ protected SinglePressAction(int iconResId, Drawable icon, CharSequence message) {
+ mIconResId = iconResId;
+ mMessageResId = 0;
+ mMessage = message;
+ mIcon = icon;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ public String getStatus() {
+ return null;
+ }
+
+ @Override
+ abstract public void onPress();
+
+ @Override
+ public CharSequence getLabelForAccessibility(Context context) {
+ if (mMessage != null) {
+ return mMessage;
+ } else {
+ return context.getString(mMessageResId);
+ }
+ }
+
+ @Override
+ public View create(
+ Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
+ View v = inflater.inflate(R.layout.global_actions_item, parent, false);
+
+ ImageView icon = v.findViewById(R.id.icon);
+ TextView messageView = v.findViewById(R.id.message);
+
+ TextView statusView = v.findViewById(R.id.status);
+ final String status = getStatus();
+ if (!TextUtils.isEmpty(status)) {
+ statusView.setText(status);
+ } else {
+ statusView.setVisibility(View.GONE);
+ }
+ if (mIcon != null) {
+ icon.setImageDrawable(mIcon);
+ icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ } else if (mIconResId != 0) {
+ icon.setImageDrawable(context.getDrawable(mIconResId));
+ }
+ if (mMessage != null) {
+ messageView.setText(mMessage);
+ } else {
+ messageView.setText(mMessageResId);
+ }
+
+ return v;
+ }
+}
diff --git a/core/java/com/android/internal/globalactions/ToggleAction.java b/core/java/com/android/internal/globalactions/ToggleAction.java
new file mode 100644
index 000000000000..9167958612ea
--- /dev/null
+++ b/core/java/com/android/internal/globalactions/ToggleAction.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.internal.globalactions;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+/**
+ * A toggle action knows whether it is on or off, and displays an icon and status message
+ * accordingly.
+ */
+public abstract class ToggleAction implements Action {
+ private static final String TAG = "ToggleAction";
+
+ public enum State {
+ Off(false),
+ TurningOn(true),
+ TurningOff(true),
+ On(false);
+
+ private final boolean inTransition;
+
+ State(boolean intermediate) {
+ inTransition = intermediate;
+ }
+
+ public boolean inTransition() {
+ return inTransition;
+ }
+ }
+
+ protected State mState = State.Off;
+
+ // prefs
+ protected int mEnabledIconResId;
+ protected int mDisabledIconResid;
+ protected int mMessageResId;
+ protected int mEnabledStatusMessageResId;
+ protected int mDisabledStatusMessageResId;
+
+ /**
+ * @param enabledIconResId The icon for when this action is on.
+ * @param disabledIconResid The icon for when this action is off.
+ * @param message The general information message, e.g 'Silent Mode'
+ * @param enabledStatusMessageResId The on status message, e.g 'sound disabled'
+ * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled'
+ */
+ public ToggleAction(int enabledIconResId,
+ int disabledIconResid,
+ int message,
+ int enabledStatusMessageResId,
+ int disabledStatusMessageResId) {
+ mEnabledIconResId = enabledIconResId;
+ mDisabledIconResid = disabledIconResid;
+ mMessageResId = message;
+ mEnabledStatusMessageResId = enabledStatusMessageResId;
+ mDisabledStatusMessageResId = disabledStatusMessageResId;
+ }
+
+ /** Override to make changes to resource IDs just before creating the View. */
+ void willCreate() {
+
+ }
+
+ @Override
+ public CharSequence getLabelForAccessibility(Context context) {
+ return context.getString(mMessageResId);
+ }
+
+ @Override
+ public View create(Context context, View convertView, ViewGroup parent,
+ LayoutInflater inflater) {
+ willCreate();
+
+ View v = inflater.inflate(R.layout.global_actions_item, parent, false);
+
+ ImageView icon = v.findViewById(R.id.icon);
+ TextView messageView = v.findViewById(R.id.message);
+ TextView statusView = v.findViewById(R.id.status);
+ final boolean enabled = isEnabled();
+
+ if (messageView != null) {
+ messageView.setText(mMessageResId);
+ messageView.setEnabled(enabled);
+ }
+
+ boolean on = ((mState == State.On) || (mState == State.TurningOn));
+ if (icon != null) {
+ icon.setImageDrawable(context.getDrawable(
+ (on ? mEnabledIconResId : mDisabledIconResid)));
+ icon.setEnabled(enabled);
+ }
+
+ if (statusView != null) {
+ statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
+ statusView.setVisibility(View.VISIBLE);
+ statusView.setEnabled(enabled);
+ }
+ v.setEnabled(enabled);
+
+ return v;
+ }
+
+ @Override
+ public final void onPress() {
+ if (mState.inTransition()) {
+ Log.w(TAG, "shouldn't be able to toggle when in transition");
+ return;
+ }
+
+ final boolean nowOn = !(mState == State.On);
+ onToggle(nowOn);
+ changeStateFromPress(nowOn);
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return !mState.inTransition();
+ }
+
+ /**
+ * Implementations may override this if their state can be in on of the intermediate
+ * states until some notification is received (e.g airplane mode is 'turning off' until
+ * we know the wireless connections are back online
+ * @param buttonOn Whether the button was turned on or off
+ */
+ protected void changeStateFromPress(boolean buttonOn) {
+ mState = buttonOn ? State.On : State.Off;
+ }
+
+ public abstract void onToggle(boolean on);
+
+ public void updateState(State state) {
+ mState = state;
+ }
+}
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index 108b6b25b0c4..e1461356cc4c 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -20,33 +20,33 @@ import android.util.Slog;
import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
-import com.android.server.statusbar.StatusBarManagerInternal;
-import com.android.server.statusbar.StatusBarManagerInternal.GlobalActionsListener;
+import com.android.server.policy.GlobalActionsProvider;
-class GlobalActions implements GlobalActionsListener {
+class GlobalActions implements GlobalActionsProvider.GlobalActionsListener {
private static final String TAG = "GlobalActions";
private static final boolean DEBUG = false;
private final Context mContext;
- private final StatusBarManagerInternal mStatusBarInternal;
+ private final GlobalActionsProvider mGlobalActionsProvider;
private final Handler mHandler;
private final WindowManagerFuncs mWindowManagerFuncs;
private LegacyGlobalActions mLegacyGlobalActions;
private boolean mKeyguardShowing;
private boolean mDeviceProvisioned;
- private boolean mStatusBarConnected;
+ private boolean mGlobalActionsAvailable;
private boolean mShowing;
public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mHandler = new Handler();
mWindowManagerFuncs = windowManagerFuncs;
- mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);
- // Some form factors do not have a status bar.
- if (mStatusBarInternal != null) {
- mStatusBarInternal.setGlobalActionsListener(this);
+ mGlobalActionsProvider = LocalServices.getService(GlobalActionsProvider.class);
+ if (mGlobalActionsProvider != null) {
+ mGlobalActionsProvider.setGlobalActionsListener(this);
+ } else {
+ Slog.i(TAG, "No GlobalActionsProvider found, defaulting to LegacyGlobalActions");
}
}
@@ -58,15 +58,15 @@ class GlobalActions implements GlobalActionsListener {
public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
if (DEBUG) Slog.d(TAG, "showDialog " + keyguardShowing + " " + deviceProvisioned);
- if (mStatusBarInternal != null && mStatusBarInternal.isGlobalActionsDisabled()) {
+ if (mGlobalActionsProvider != null && mGlobalActionsProvider.isGlobalActionsDisabled()) {
return;
}
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = deviceProvisioned;
mShowing = true;
- if (mStatusBarConnected) {
- mStatusBarInternal.showGlobalActions();
+ if (mGlobalActionsAvailable) {
mHandler.postDelayed(mShowTimeout, 5000);
+ mGlobalActionsProvider.showGlobalActions();
} else {
// SysUI isn't alive, show legacy menu.
ensureLegacyCreated();
@@ -88,11 +88,12 @@ class GlobalActions implements GlobalActionsListener {
}
@Override
- public void onStatusBarConnectedChanged(boolean connected) {
- if (DEBUG) Slog.d(TAG, "onStatusBarConnectedChanged " + connected);
- mStatusBarConnected = connected;
- if (mShowing && !mStatusBarConnected) {
- // Status bar died but we need to be showing global actions still, show the legacy.
+ public void onGlobalActionsAvailableChanged(boolean available) {
+ if (DEBUG) Slog.d(TAG, "onGlobalActionsAvailableChanged " + available);
+ mGlobalActionsAvailable = available;
+ if (mShowing && !mGlobalActionsAvailable) {
+ // Global actions provider died but we need to be showing global actions still, show the
+ // legacy global acrions provider.
ensureLegacyCreated();
mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
}
diff --git a/services/core/java/com/android/server/policy/GlobalActionsProvider.java b/services/core/java/com/android/server/policy/GlobalActionsProvider.java
new file mode 100644
index 000000000000..d414314db2b5
--- /dev/null
+++ b/services/core/java/com/android/server/policy/GlobalActionsProvider.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+package com.android.server.policy;
+
+/** Used with LocalServices to add custom handling to global actions. */
+public interface GlobalActionsProvider {
+ /** @return {@code true} if the dialog is enabled. */
+ boolean isGlobalActionsDisabled();
+ /** Set the listener that will handle various global actions evetns. */
+ void setGlobalActionsListener(GlobalActionsListener listener);
+ /** Show the global actions UI to the user. */
+ void showGlobalActions();
+
+ /** Listener to pass global actions events back to system. */
+ public interface GlobalActionsListener {
+ /**
+ * Called when sysui starts and connects its status bar, or when the status bar binder
+ * dies indicating sysui is no longer alive.
+ */
+ void onGlobalActionsAvailableChanged(boolean available);
+
+ /**
+ * Callback from sysui to notify system that global actions has been successfully shown.
+ */
+ void onGlobalActionsShown();
+
+ /**
+ * Callback from sysui to notify system that the user has dismissed global actions and
+ * it no longer needs to be displayed (even if sysui dies).
+ */
+ void onGlobalActionsDismissed();
+ }
+}
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 96d062df0fea..9cb2441d5662 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -17,18 +17,24 @@
package com.android.server.policy;
import com.android.internal.app.AlertController;
-import com.android.internal.app.AlertController.AlertParams;
+import com.android.internal.globalactions.Action;
+import com.android.internal.globalactions.ActionsAdapter;
+import com.android.internal.globalactions.ActionsDialog;
+import com.android.internal.globalactions.LongPressAction;
+import com.android.internal.globalactions.SinglePressAction;
+import com.android.internal.globalactions.ToggleAction;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.internal.R;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
-import com.android.internal.R;
+import com.android.internal.util.EmergencyAffordanceManager;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.policy.PowerAction;
+import com.android.server.policy.RestartAction;
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
import android.app.ActivityManager;
-import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -40,7 +46,6 @@ import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@@ -55,23 +60,14 @@ import android.service.dreams.IDreamManager;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
-import android.util.TypedValue;
-import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.ListView;
-import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
@@ -107,12 +103,12 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
private final Runnable mOnDismiss;
private ArrayList<Action> mItems;
- private GlobalActionsDialog mDialog;
+ private ActionsDialog mDialog;
private Action mSilentModeAction;
private ToggleAction mAirplaneModeOn;
- private MyAdapter mAdapter;
+ private ActionsAdapter mAdapter;
private boolean mKeyguardShowing = false;
private boolean mDeviceProvisioned = false;
@@ -217,7 +213,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
* Create the global actions dialog.
* @return A new dialog.
*/
- private GlobalActionsDialog createDialog() {
+ private ActionsDialog createDialog() {
// Simple toggle style if there's no vibrator, otherwise use a tri-state
if (!mHasVibrator) {
mSilentModeAction = new SilentModeToggleAction();
@@ -232,7 +228,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
R.string.global_actions_airplane_mode_off_status) {
@Override
- void onToggle(boolean on) {
+ public void onToggle(boolean on) {
if (mHasTelephony && Boolean.parseBoolean(
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
mIsWaitingForEcmExit = true;
@@ -282,7 +278,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
continue;
}
if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
- mItems.add(new PowerAction());
+ mItems.add(new PowerAction(mContext, mWindowManagerFuncs));
} else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
mItems.add(mAirplaneModeOn);
} else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
@@ -307,7 +303,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
} else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
mItems.add(getAssistAction());
} else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {
- mItems.add(new RestartAction());
+ mItems.add(new RestartAction(mContext, mWindowManagerFuncs));
} else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
@@ -319,14 +315,15 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
mItems.add(getEmergencyAction());
}
- mAdapter = new MyAdapter();
+ mAdapter = new ActionsAdapter(mContext, mItems,
+ () -> mDeviceProvisioned, () -> mKeyguardShowing);
- AlertParams params = new AlertParams(mContext);
+ AlertController.AlertParams params = new AlertController.AlertParams(mContext);
params.mAdapter = mAdapter;
params.mOnClickListener = this;
params.mForceInverseBackground = true;
- GlobalActionsDialog dialog = new GlobalActionsDialog(mContext, params);
+ ActionsDialog dialog = new ActionsDialog(mContext, params);
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.getListView().setItemsCanFocus(true);
@@ -350,71 +347,6 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
return dialog;
}
- private final class PowerAction extends SinglePressAction implements LongPressAction {
- private PowerAction() {
- super(com.android.internal.R.drawable.ic_lock_power_off,
- R.string.global_action_power_off);
- }
-
- @Override
- public boolean onLongPress() {
- UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
- mWindowManagerFuncs.rebootSafeMode(true);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean showDuringKeyguard() {
- return true;
- }
-
- @Override
- public boolean showBeforeProvisioning() {
- return true;
- }
-
- @Override
- public void onPress() {
- // shutdown by making sure radio and power are handled accordingly.
- mWindowManagerFuncs.shutdown(false /* confirm */);
- }
- }
-
- private final class RestartAction extends SinglePressAction implements LongPressAction {
- private RestartAction() {
- super(R.drawable.ic_restart, R.string.global_action_restart);
- }
-
- @Override
- public boolean onLongPress() {
- UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
- mWindowManagerFuncs.rebootSafeMode(true);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean showDuringKeyguard() {
- return true;
- }
-
- @Override
- public boolean showBeforeProvisioning() {
- return true;
- }
-
- @Override
- public void onPress() {
- mWindowManagerFuncs.reboot(false /* confirm */);
- }
- }
-
-
private class BugReportAction extends SinglePressAction implements LongPressAction {
public BugReportAction() {
@@ -693,330 +625,12 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
mAdapter.getItem(which).onPress();
}
- /**
- * The adapter used for the list within the global actions dialog, taking
- * into account whether the keyguard is showing via
- * {@link LegacyGlobalActions#mKeyguardShowing} and whether the device is provisioned
- * via {@link LegacyGlobalActions#mDeviceProvisioned}.
- */
- private class MyAdapter extends BaseAdapter {
-
- @Override
- public int getCount() {
- int count = 0;
-
- for (int i = 0; i < mItems.size(); i++) {
- final Action action = mItems.get(i);
-
- if (mKeyguardShowing && !action.showDuringKeyguard()) {
- continue;
- }
- if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
- continue;
- }
- count++;
- }
- return count;
- }
-
- @Override
- public boolean isEnabled(int position) {
- return getItem(position).isEnabled();
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- @Override
- public Action getItem(int position) {
-
- int filteredPos = 0;
- for (int i = 0; i < mItems.size(); i++) {
- final Action action = mItems.get(i);
- if (mKeyguardShowing && !action.showDuringKeyguard()) {
- continue;
- }
- if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
- continue;
- }
- if (filteredPos == position) {
- return action;
- }
- filteredPos++;
- }
-
- throw new IllegalArgumentException("position " + position
- + " out of range of showable actions"
- + ", filtered count=" + getCount()
- + ", keyguardshowing=" + mKeyguardShowing
- + ", provisioned=" + mDeviceProvisioned);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Action action = getItem(position);
- return action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
- }
- }
-
// note: the scheme below made more sense when we were planning on having
// 8 different things in the global actions dialog. seems overkill with
// only 3 items now, but may as well keep this flexible approach so it will
// be easy should someone decide at the last minute to include something
// else, such as 'enable wifi', or 'enable bluetooth'
- /**
- * What each item in the global actions dialog must be able to support.
- */
- private interface Action {
- /**
- * @return Text that will be announced when dialog is created. null
- * for none.
- */
- CharSequence getLabelForAccessibility(Context context);
-
- View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater);
-
- void onPress();
-
- /**
- * @return whether this action should appear in the dialog when the keygaurd
- * is showing.
- */
- boolean showDuringKeyguard();
-
- /**
- * @return whether this action should appear in the dialog before the
- * device is provisioned.
- */
- boolean showBeforeProvisioning();
-
- boolean isEnabled();
- }
-
- /**
- * An action that also supports long press.
- */
- private interface LongPressAction extends Action {
- boolean onLongPress();
- }
-
- /**
- * A single press action maintains no state, just responds to a press
- * and takes an action.
- */
- private static abstract class SinglePressAction implements Action {
- private final int mIconResId;
- private final Drawable mIcon;
- private final int mMessageResId;
- private final CharSequence mMessage;
-
- protected SinglePressAction(int iconResId, int messageResId) {
- mIconResId = iconResId;
- mMessageResId = messageResId;
- mMessage = null;
- mIcon = null;
- }
-
- protected SinglePressAction(int iconResId, Drawable icon, CharSequence message) {
- mIconResId = iconResId;
- mMessageResId = 0;
- mMessage = message;
- mIcon = icon;
- }
-
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- public String getStatus() {
- return null;
- }
-
- @Override
- abstract public void onPress();
-
- @Override
- public CharSequence getLabelForAccessibility(Context context) {
- if (mMessage != null) {
- return mMessage;
- } else {
- return context.getString(mMessageResId);
- }
- }
-
- @Override
- public View create(
- Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
- View v = inflater.inflate(R.layout.global_actions_item, parent, false);
-
- ImageView icon = (ImageView) v.findViewById(R.id.icon);
- TextView messageView = (TextView) v.findViewById(R.id.message);
-
- TextView statusView = (TextView) v.findViewById(R.id.status);
- final String status = getStatus();
- if (!TextUtils.isEmpty(status)) {
- statusView.setText(status);
- } else {
- statusView.setVisibility(View.GONE);
- }
- if (mIcon != null) {
- icon.setImageDrawable(mIcon);
- icon.setScaleType(ScaleType.CENTER_CROP);
- } else if (mIconResId != 0) {
- icon.setImageDrawable(context.getDrawable(mIconResId));
- }
- if (mMessage != null) {
- messageView.setText(mMessage);
- } else {
- messageView.setText(mMessageResId);
- }
-
- return v;
- }
- }
-
- /**
- * A toggle action knows whether it is on or off, and displays an icon
- * and status message accordingly.
- */
- private static abstract class ToggleAction implements Action {
-
- enum State {
- Off(false),
- TurningOn(true),
- TurningOff(true),
- On(false);
-
- private final boolean inTransition;
-
- State(boolean intermediate) {
- inTransition = intermediate;
- }
-
- public boolean inTransition() {
- return inTransition;
- }
- }
-
- protected State mState = State.Off;
-
- // prefs
- protected int mEnabledIconResId;
- protected int mDisabledIconResid;
- protected int mMessageResId;
- protected int mEnabledStatusMessageResId;
- protected int mDisabledStatusMessageResId;
-
- /**
- * @param enabledIconResId The icon for when this action is on.
- * @param disabledIconResid The icon for when this action is off.
- * @param message The general information message, e.g 'Silent Mode'
- * @param enabledStatusMessageResId The on status message, e.g 'sound disabled'
- * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled'
- */
- public ToggleAction(int enabledIconResId,
- int disabledIconResid,
- int message,
- int enabledStatusMessageResId,
- int disabledStatusMessageResId) {
- mEnabledIconResId = enabledIconResId;
- mDisabledIconResid = disabledIconResid;
- mMessageResId = message;
- mEnabledStatusMessageResId = enabledStatusMessageResId;
- mDisabledStatusMessageResId = disabledStatusMessageResId;
- }
-
- /**
- * Override to make changes to resource IDs just before creating the
- * View.
- */
- void willCreate() {
-
- }
-
- @Override
- public CharSequence getLabelForAccessibility(Context context) {
- return context.getString(mMessageResId);
- }
-
- @Override
- public View create(Context context, View convertView, ViewGroup parent,
- LayoutInflater inflater) {
- willCreate();
-
- View v = inflater.inflate(R
- .layout.global_actions_item, parent, false);
-
- ImageView icon = (ImageView) v.findViewById(R.id.icon);
- TextView messageView = (TextView) v.findViewById(R.id.message);
- TextView statusView = (TextView) v.findViewById(R.id.status);
- final boolean enabled = isEnabled();
-
- if (messageView != null) {
- messageView.setText(mMessageResId);
- messageView.setEnabled(enabled);
- }
-
- boolean on = ((mState == State.On) || (mState == State.TurningOn));
- if (icon != null) {
- icon.setImageDrawable(context.getDrawable(
- (on ? mEnabledIconResId : mDisabledIconResid)));
- icon.setEnabled(enabled);
- }
-
- if (statusView != null) {
- statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
- statusView.setVisibility(View.VISIBLE);
- statusView.setEnabled(enabled);
- }
- v.setEnabled(enabled);
-
- return v;
- }
-
- @Override
- public final void onPress() {
- if (mState.inTransition()) {
- Log.w(TAG, "shouldn't be able to toggle when in transition");
- return;
- }
-
- final boolean nowOn = !(mState == State.On);
- onToggle(nowOn);
- changeStateFromPress(nowOn);
- }
-
- @Override
- public boolean isEnabled() {
- return !mState.inTransition();
- }
-
- /**
- * Implementations may override this if their state can be in on of the intermediate
- * states until some notification is received (e.g airplane mode is 'turning off' until
- * we know the wireless connections are back online
- * @param buttonOn Whether the button was turned on or off
- */
- protected void changeStateFromPress(boolean buttonOn) {
- mState = buttonOn ? State.On : State.Off;
- }
-
- abstract void onToggle(boolean on);
-
- public void updateState(State state) {
- mState = state;
- }
- }
-
private class SilentModeToggleAction extends ToggleAction {
public SilentModeToggleAction() {
super(R.drawable.ic_audio_vol_mute,
@@ -1027,7 +641,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
}
@Override
- void onToggle(boolean on) {
+ public void onToggle(boolean on) {
if (on) {
mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
} else {
@@ -1226,71 +840,4 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn
mAirplaneState = on ? ToggleAction.State.On : ToggleAction.State.Off;
}
}
-
- private static final class GlobalActionsDialog extends Dialog implements DialogInterface {
- private final Context mContext;
- private final AlertController mAlert;
- private final MyAdapter mAdapter;
-
- public GlobalActionsDialog(Context context, AlertParams params) {
- super(context, getDialogTheme(context));
- mContext = getContext();
- mAlert = AlertController.create(mContext, this, getWindow());
- mAdapter = (MyAdapter) params.mAdapter;
- params.apply(mAlert);
- }
-
- private static int getDialogTheme(Context context) {
- TypedValue outValue = new TypedValue();
- context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
- outValue, true);
- return outValue.resourceId;
- }
-
- @Override
- protected void onStart() {
- super.setCanceledOnTouchOutside(true);
- super.onStart();
- }
-
- public ListView getListView() {
- return mAlert.getListView();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mAlert.installContent();
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
- for (int i = 0; i < mAdapter.getCount(); ++i) {
- CharSequence label =
- mAdapter.getItem(i).getLabelForAccessibility(getContext());
- if (label != null) {
- event.getText().add(label);
- }
- }
- }
- return super.dispatchPopulateAccessibilityEvent(event);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (mAlert.onKeyDown(keyCode, event)) {
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (mAlert.onKeyUp(keyCode, event)) {
- return true;
- }
- return super.onKeyUp(keyCode, event);
- }
- }
}
diff --git a/services/core/java/com/android/server/policy/PowerAction.java b/services/core/java/com/android/server/policy/PowerAction.java
new file mode 100644
index 000000000000..d2de58e96551
--- /dev/null
+++ b/services/core/java/com/android/server/policy/PowerAction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.server.policy;
+
+import android.content.Context;
+import android.os.UserManager;
+import com.android.internal.globalactions.LongPressAction;
+import com.android.internal.globalactions.SinglePressAction;
+import com.android.internal.R;
+import com.android.server.policy.WindowManagerPolicy;
+
+public final class PowerAction extends SinglePressAction implements LongPressAction {
+ private final Context mContext;
+ private final WindowManagerPolicy.WindowManagerFuncs mWindowManagerFuncs;
+
+ public PowerAction(Context context,
+ WindowManagerPolicy.WindowManagerFuncs windowManagerFuncs) {
+ super(R.drawable.ic_lock_power_off, R.string.global_action_power_off);
+ mContext = context;
+ mWindowManagerFuncs = windowManagerFuncs;
+ }
+
+ @Override
+ public boolean onLongPress() {
+ UserManager um = mContext.getSystemService(UserManager.class);
+ if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+ mWindowManagerFuncs.rebootSafeMode(true);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void onPress() {
+ // shutdown by making sure radio and power are handled accordingly.
+ mWindowManagerFuncs.shutdown(false /* confirm */);
+ }
+}
diff --git a/services/core/java/com/android/server/policy/RestartAction.java b/services/core/java/com/android/server/policy/RestartAction.java
new file mode 100644
index 000000000000..0f13da82dad3
--- /dev/null
+++ b/services/core/java/com/android/server/policy/RestartAction.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.server.policy;
+
+import android.content.Context;
+import android.os.UserManager;
+import com.android.internal.globalactions.LongPressAction;
+import com.android.internal.globalactions.SinglePressAction;
+import com.android.internal.R;
+import com.android.server.policy.WindowManagerPolicy;
+
+public final class RestartAction extends SinglePressAction implements LongPressAction {
+ private final Context mContext;
+ private final WindowManagerPolicy.WindowManagerFuncs mWindowManagerFuncs;
+
+ public RestartAction(Context context,
+ WindowManagerPolicy.WindowManagerFuncs windowManagerFuncs) {
+ super(R.drawable.ic_restart, R.string.global_action_restart);
+ mContext = context;
+ mWindowManagerFuncs = windowManagerFuncs;
+ }
+
+ @Override
+ public boolean onLongPress() {
+ UserManager um = mContext.getSystemService(UserManager.class);
+ if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
+ mWindowManagerFuncs.rebootSafeMode(true);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void onPress() {
+ mWindowManagerFuncs.reboot(false /* confirm */);
+ }
+}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 3ab771b7c6ec..095eaa5fde67 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -79,10 +79,6 @@ public interface StatusBarManagerInternal {
void setCurrentUser(int newUserId);
- boolean isGlobalActionsDisabled();
- void setGlobalActionsListener(GlobalActionsListener listener);
- void showGlobalActions();
-
/**
* Set whether the top app currently hides the statusbar.
*
@@ -98,23 +94,4 @@ public interface StatusBarManagerInternal {
* @param rotation rotation suggestion
*/
void onProposedRotationChanged(int rotation, boolean isValid);
-
- public interface GlobalActionsListener {
- /**
- * Called when sysui starts and connects its status bar, or when the status bar binder
- * dies indicating sysui is no longer alive.
- */
- void onStatusBarConnectedChanged(boolean connected);
-
- /**
- * Callback from sysui to notify system that global actions has been successfully shown.
- */
- void onGlobalActionsShown();
-
- /**
- * Callback from sysui to notify system that the user has dismissed global actions and
- * it no longer needs to be displayed (even if sysui dies).
- */
- void onGlobalActionsDismissed();
- }
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 343fb91eec53..59fce64b2f2c 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -47,8 +47,8 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationDelegate;
+import com.android.server.policy.GlobalActionsProvider;
import com.android.server.power.ShutdownThread;
-import com.android.server.statusbar.StatusBarManagerInternal.GlobalActionsListener;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -74,7 +74,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
// for disabling the status bar
private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
- private GlobalActionsListener mGlobalActionListener;
+ private GlobalActionsProvider.GlobalActionsListener mGlobalActionListener;
private IBinder mSysUiVisToken = new Binder();
private int mDisabled1 = 0;
private int mDisabled2 = 0;
@@ -162,6 +162,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
mWindowManager = windowManager;
LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
+ LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider);
}
/**
@@ -375,26 +376,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
@Override
- public boolean isGlobalActionsDisabled() {
- return (mDisabled2 & DISABLE2_GLOBAL_ACTIONS) != 0;
- }
-
- @Override
- public void setGlobalActionsListener(GlobalActionsListener listener) {
- mGlobalActionListener = listener;
- mGlobalActionListener.onStatusBarConnectedChanged(mBar != null);
- }
-
- @Override
- public void showGlobalActions() {
- if (mBar != null) {
- try {
- mBar.showGlobalActionsMenu();
- } catch (RemoteException ex) {}
- }
- }
-
- @Override
public void setTopAppHidesStatusBar(boolean hidesStatusBar) {
if (mBar != null) {
try {
@@ -427,6 +408,28 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
};
+ private final GlobalActionsProvider mGlobalActionsProvider = new GlobalActionsProvider() {
+ @Override
+ public boolean isGlobalActionsDisabled() {
+ return (mDisabled2 & DISABLE2_GLOBAL_ACTIONS) != 0;
+ }
+
+ @Override
+ public void setGlobalActionsListener(GlobalActionsProvider.GlobalActionsListener listener) {
+ mGlobalActionListener = listener;
+ mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null);
+ }
+
+ @Override
+ public void showGlobalActions() {
+ if (mBar != null) {
+ try {
+ mBar.showGlobalActionsMenu();
+ } catch (RemoteException ex) {}
+ }
+ }
+ };
+
// ================================================================================
// From IStatusBarService
// ================================================================================
@@ -892,7 +895,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
private void notifyBarAttachChanged() {
mHandler.post(() -> {
if (mGlobalActionListener == null) return;
- mGlobalActionListener.onStatusBarConnectedChanged(mBar != null);
+ mGlobalActionListener.onGlobalActionsAvailableChanged(mBar != null);
});
}