Merge "Support for notification panel key on ATV"
This commit is contained in:
committed by
Android (Google) Code Review
commit
c14b6b52ff
@@ -671,6 +671,9 @@ package android.app {
|
||||
method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
|
||||
method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
|
||||
method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
|
||||
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL";
|
||||
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL";
|
||||
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL";
|
||||
}
|
||||
|
||||
public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.app;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.SystemApi;
|
||||
@@ -130,6 +131,73 @@ public class NotificationManager {
|
||||
public static final String ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED =
|
||||
"android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED";
|
||||
|
||||
/**
|
||||
* Activity action: Toggle notification panel of the specified handler.
|
||||
*
|
||||
* <p><strong>Important:</strong>You must protect the activity that handles this action with
|
||||
* the {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission to ensure that only
|
||||
* the SystemUI can launch this activity. Activities that are not properly protected will not
|
||||
* be launched.
|
||||
*
|
||||
* <p class="note">This is currently only used on TV to allow a system app to handle the
|
||||
* notification panel. The package handling the notification panel has to be specified by
|
||||
* config_notificationHandlerPackage in values/config.xml.
|
||||
*
|
||||
* Input: nothing
|
||||
* Output: nothing
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
|
||||
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL =
|
||||
"android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL";
|
||||
|
||||
/**
|
||||
* Activity action: Open notification panel of the specified handler.
|
||||
*
|
||||
* <p><strong>Important:</strong>You must protect the activity that handles this action with
|
||||
* the {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission to ensure that only
|
||||
* the SystemUI can launch this activity. Activities that are not properly protected will
|
||||
* not be launched.
|
||||
*
|
||||
* <p class="note"> This is currently only used on TV to allow a system app to handle the
|
||||
* notification panel. The package handling the notification panel has to be specified by
|
||||
* config_notificationHandlerPackage in values/config.xml.
|
||||
*
|
||||
* Input: nothing
|
||||
* Output: nothing
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
|
||||
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL =
|
||||
"android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL";
|
||||
|
||||
/**
|
||||
* Intent that is broadcast when the notification panel of the specified handler is to be
|
||||
* closed.
|
||||
*
|
||||
* <p><strong>Important:</strong>You should protect the receiver that handles this action with
|
||||
* the {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission to ensure that only
|
||||
* the SystemUI can send this broadcast to the notification handler.
|
||||
*
|
||||
* <p class="note"> This is currently only used on TV to allow a system app to handle the
|
||||
* notification panel. The package handling the notification panel has to be specified by
|
||||
* config_notificationHandlerPackage in values/config.xml. This is a protected intent that can
|
||||
* only be sent by the system.
|
||||
*
|
||||
* Input: nothing.
|
||||
* Output: nothing.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
|
||||
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL =
|
||||
"android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL";
|
||||
|
||||
/**
|
||||
* Extra for {@link #ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED} containing the id of the
|
||||
* {@link NotificationChannel} which has a new blocked state.
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
<!-- @deprecated This is rarely used and will be phased out soon. -->
|
||||
<protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
|
||||
|
||||
<protected-broadcast android:name="android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL" />
|
||||
|
||||
<protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" />
|
||||
<protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" />
|
||||
<protected-broadcast android:name="android.app.action.ENTER_CAR_MODE_PRIORITIZED" />
|
||||
|
||||
@@ -1166,6 +1166,7 @@
|
||||
0 - Nothing
|
||||
1 - Launch all apps intent
|
||||
2 - Launch assist intent
|
||||
3 - Launch notification panel
|
||||
This needs to match the constants in
|
||||
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
|
||||
-->
|
||||
@@ -3390,6 +3391,9 @@
|
||||
service. -->
|
||||
<string name="config_tvRemoteServicePackage" translatable="false"></string>
|
||||
|
||||
<!-- The package name of the package implementing the custom notification panel -->
|
||||
<string name="config_notificationHandlerPackage" translatable="false"></string>
|
||||
|
||||
<!-- True if the device supports persisting security logs across reboots.
|
||||
This requires the device's kernel to have pstore and pmsg enabled,
|
||||
and DRAM to be powered and refreshed through all stages of reboot. -->
|
||||
|
||||
@@ -3047,6 +3047,9 @@
|
||||
<java-symbol type="string" name="config_tvRemoteServicePackage" />
|
||||
<java-symbol type="string" name="notification_messaging_title_template" />
|
||||
|
||||
<!-- Notification handler / dashboard package -->
|
||||
<java-symbol type="string" name="config_notificationHandlerPackage" />
|
||||
|
||||
<java-symbol type="bool" name="config_supportPreRebootSecurityLogs" />
|
||||
|
||||
<java-symbol type="dimen" name="notification_media_image_margin_end" />
|
||||
|
||||
@@ -223,7 +223,7 @@ key 200 MEDIA_PLAY
|
||||
key 201 MEDIA_PAUSE
|
||||
# key 202 "KEY_PROG3"
|
||||
# key 203 "KEY_PROG4"
|
||||
# key 204 (undefined)
|
||||
key 204 NOTIFICATION
|
||||
# key 205 "KEY_SUSPEND"
|
||||
# key 206 "KEY_CLOSE"
|
||||
key 207 MEDIA_PLAY
|
||||
|
||||
@@ -671,6 +671,9 @@ package android.app {
|
||||
method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
|
||||
method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
|
||||
method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
|
||||
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL";
|
||||
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL";
|
||||
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL";
|
||||
}
|
||||
|
||||
public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<item>com.android.systemui.util.NotificationChannels</item>
|
||||
<item>com.android.systemui.volume.VolumeUI</item>
|
||||
<item>com.android.systemui.statusbar.tv.TvStatusBar</item>
|
||||
<item>com.android.systemui.statusbar.tv.TvNotificationPanel</item>
|
||||
<item>com.android.systemui.usb.StorageNotification</item>
|
||||
<item>com.android.systemui.power.PowerUI</item>
|
||||
<item>com.android.systemui.media.RingtonePlayer</item>
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.android.systemui.shortcut.ShortcutKeyDispatcher;
|
||||
import com.android.systemui.statusbar.dagger.StatusBarModule;
|
||||
import com.android.systemui.statusbar.notification.InstantAppNotifier;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.tv.TvNotificationPanel;
|
||||
import com.android.systemui.statusbar.tv.TvStatusBar;
|
||||
import com.android.systemui.theme.ThemeOverlayController;
|
||||
import com.android.systemui.toast.ToastUI;
|
||||
@@ -156,6 +157,12 @@ public abstract class SystemUIBinder {
|
||||
@ClassKey(TvStatusBar.class)
|
||||
public abstract SystemUI bindsTvStatusBar(TvStatusBar sysui);
|
||||
|
||||
/** Inject into TvNotificationPanel. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(TvNotificationPanel.class)
|
||||
public abstract SystemUI bindsTvNotificationPanel(TvNotificationPanel sysui);
|
||||
|
||||
/** Inject into VolumeUI. */
|
||||
@Binds
|
||||
@IntoMap
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.systemui.statusbar.tv;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Offers control methods for the notification panel handler on TV devices.
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class TvNotificationPanel extends SystemUI implements CommandQueue.Callbacks {
|
||||
private static final String TAG = "TvNotificationPanel";
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final String mNotificationHandlerPackage;
|
||||
|
||||
@Inject
|
||||
public TvNotificationPanel(Context context, CommandQueue commandQueue) {
|
||||
super(context);
|
||||
mCommandQueue = commandQueue;
|
||||
mNotificationHandlerPackage = mContext.getResources().getString(
|
||||
com.android.internal.R.string.config_notificationHandlerPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
mCommandQueue.addCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void togglePanel() {
|
||||
if (!mNotificationHandlerPackage.isEmpty()) {
|
||||
startNotificationHandlerActivity(
|
||||
new Intent(NotificationManager.ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateExpandNotificationsPanel() {
|
||||
if (!mNotificationHandlerPackage.isEmpty()) {
|
||||
startNotificationHandlerActivity(
|
||||
new Intent(NotificationManager.ACTION_OPEN_NOTIFICATION_HANDLER_PANEL));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateCollapsePanels(int flags, boolean force) {
|
||||
if (!mNotificationHandlerPackage.isEmpty()
|
||||
&& (flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
|
||||
Intent closeNotificationIntent = new Intent(
|
||||
NotificationManager.ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL);
|
||||
closeNotificationIntent.setPackage(mNotificationHandlerPackage);
|
||||
mContext.sendBroadcastAsUser(closeNotificationIntent, UserHandle.CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the activity intent if all of the following are true
|
||||
* <ul>
|
||||
* <li> the notification handler package is a system component </li>
|
||||
* <li> the provided intent is handled by the notification handler package </li>
|
||||
* <li> the notification handler requests the
|
||||
* {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission for the given intent</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param intent The intent for starting the desired activity
|
||||
*/
|
||||
private void startNotificationHandlerActivity(Intent intent) {
|
||||
intent.setPackage(mNotificationHandlerPackage);
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_SYSTEM_ONLY);
|
||||
if (ri != null && ri.activityInfo != null) {
|
||||
if (ri.activityInfo.permission != null && ri.activityInfo.permission.equals(
|
||||
Manifest.permission.STATUS_BAR_SERVICE)) {
|
||||
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
|
||||
} else {
|
||||
Log.e(TAG,
|
||||
"Not launching notification handler activity: Notification handler does "
|
||||
+ "not require the STATUS_BAR_SERVICE permission for intent "
|
||||
+ intent.getAction());
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG,
|
||||
"Not launching notification handler activity: Could not resolve activityInfo "
|
||||
+ "for intent "
|
||||
+ intent.getAction());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,9 @@
|
||||
package com.android.systemui.statusbar.tv;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.systemui.R;
|
||||
@@ -49,9 +45,6 @@ import dagger.Lazy;
|
||||
@SysUISingleton
|
||||
public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
|
||||
|
||||
private static final String ACTION_OPEN_TV_NOTIFICATIONS_PANEL =
|
||||
"com.android.tv.action.OPEN_NOTIFICATIONS_PANEL";
|
||||
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final Lazy<AssistManager> mAssistManagerLazy;
|
||||
|
||||
@@ -74,24 +67,11 @@ public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
|
||||
// If the system process isn't there we're doomed anyway.
|
||||
}
|
||||
|
||||
if (mContext.getResources().getBoolean(R.bool.audio_recording_disclosure_enabled)) {
|
||||
if (mContext.getResources().getBoolean(R.bool.audio_recording_disclosure_enabled)) {
|
||||
// Creating AudioRecordingDisclosureBar and just letting it run
|
||||
new AudioRecordingDisclosureBar(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateExpandNotificationsPanel() {
|
||||
startSystemActivity(new Intent(ACTION_OPEN_TV_NOTIFICATIONS_PANEL));
|
||||
}
|
||||
|
||||
private void startSystemActivity(Intent intent) {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_SYSTEM_ONLY);
|
||||
if (ri != null && ri.activityInfo != null) {
|
||||
intent.setPackage(ri.activityInfo.packageName);
|
||||
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -281,7 +281,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
static final int LONG_PRESS_HOME_NOTHING = 0;
|
||||
static final int LONG_PRESS_HOME_ALL_APPS = 1;
|
||||
static final int LONG_PRESS_HOME_ASSIST = 2;
|
||||
static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST;
|
||||
static final int LONG_PRESS_HOME_NOTIFICATION_PANEL = 3;
|
||||
static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_NOTIFICATION_PANEL;
|
||||
|
||||
// must match: config_doubleTapOnHomeBehavior in config.xml
|
||||
static final int DOUBLE_TAP_HOME_NOTHING = 0;
|
||||
@@ -1694,8 +1695,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
case LONG_PRESS_HOME_ASSIST:
|
||||
launchAssistAction(null, deviceId);
|
||||
break;
|
||||
case LONG_PRESS_HOME_NOTIFICATION_PANEL:
|
||||
IStatusBarService statusBarService = getStatusBarService();
|
||||
if (statusBarService != null) {
|
||||
try {
|
||||
statusBarService.togglePanel();
|
||||
} catch (RemoteException e) {
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.w(TAG, "Undefined home long press behavior: "
|
||||
Log.w(TAG, "Undefined long press on home behavior: "
|
||||
+ mLongPressOnHomeBehavior);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user