1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.media; 18 19 import android.content.Context; 20 import android.provider.DeviceConfig; 21 import android.text.TextUtils; 22 23 import java.io.PrintWriter; 24 import java.util.Set; 25 26 class MediaSessionDeviceConfig { 27 /** 28 * Denotes the duration for which a media button receiver will be exempted from 29 * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the 30 * background state while it receives a media key event. 31 */ 32 private static final String KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS = 33 "media_button_receiver_fgs_allowlist_duration_ms"; 34 private static final long DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS = 10_000; 35 private static volatile long sMediaButtonReceiverFgsAllowlistDurationMs = 36 DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS; 37 38 /** 39 * Denotes the duration for which an app receiving a media session callback will be 40 * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if 41 * it is in the background state while it receives a media session callback. 42 */ 43 private static final String KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS = 44 "media_session_calback_fgs_allowlist_duration_ms"; 45 private static final long DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS = 10_000; 46 private static volatile long sMediaSessionCallbackFgsAllowlistDurationMs = 47 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS; 48 49 50 /** 51 * Denotes the duration for which an app receiving a media session callback and the FGS started 52 * there can be temporarily allowed to have while-in-use permissions such as 53 * location/camera/microphone for a duration of time. 54 */ 55 private static final String KEY_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS = 56 "media_session_callback_fgs_while_in_use_temp_allow_duration_ms"; 57 private static final long DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS 58 = 10_000; 59 private static volatile long sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs = 60 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS; 61 62 /** 63 * Denotes the duration (in milliseconds) that a media session can remain in an engaged state, 64 * where it is only considered engaged if transitioning from active playback. 65 */ 66 private static final String KEY_MEDIA_SESSION_TEMP_USER_ENGAGED_DURATION_MS = 67 "media_session_temp_user_engaged_duration_ms"; 68 private static final long DEFAULT_MEDIA_SESSION_TEMP_USER_ENGAGED_DURATION_MS = 600_000; 69 private static volatile long sMediaSessionTempUserEngagedDurationMs = 70 DEFAULT_MEDIA_SESSION_TEMP_USER_ENGAGED_DURATION_MS; 71 refresh(DeviceConfig.Properties properties)72 private static void refresh(DeviceConfig.Properties properties) { 73 final Set<String> keys = properties.getKeyset(); 74 properties.getKeyset().forEach(key -> { 75 switch (key) { 76 case KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS: 77 sMediaButtonReceiverFgsAllowlistDurationMs = properties.getLong(key, 78 DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS); 79 break; 80 case KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS: 81 sMediaSessionCallbackFgsAllowlistDurationMs = properties.getLong(key, 82 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS); 83 break; 84 case KEY_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS: 85 sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs = properties.getLong(key, 86 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS); 87 break; 88 case KEY_MEDIA_SESSION_TEMP_USER_ENGAGED_DURATION_MS: 89 sMediaSessionTempUserEngagedDurationMs = properties.getLong(key, 90 DEFAULT_MEDIA_SESSION_TEMP_USER_ENGAGED_DURATION_MS); 91 break; 92 } 93 }); 94 } 95 initialize(Context context)96 public static void initialize(Context context) { 97 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_MEDIA, 98 context.getMainExecutor(), properties -> refresh(properties)); 99 refresh(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_MEDIA)); 100 } 101 102 /** 103 * Returns the duration for which a media button receiver will be exempted from 104 * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the 105 * background state while it receives a media key event. 106 */ getMediaButtonReceiverFgsAllowlistDurationMs()107 public static long getMediaButtonReceiverFgsAllowlistDurationMs() { 108 return sMediaButtonReceiverFgsAllowlistDurationMs; 109 } 110 111 /** 112 * Returns the duration for which an app receiving a media session callback will be 113 * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if 114 * it is in the background state while it receives a media session callback. 115 */ getMediaSessionCallbackFgsAllowlistDurationMs()116 public static long getMediaSessionCallbackFgsAllowlistDurationMs() { 117 return sMediaSessionCallbackFgsAllowlistDurationMs; 118 } 119 120 /** 121 * Return the duration for which an app receiving a media session callback and the FGS started 122 * there can be temporarily allowed to have while-in-use permissions such as 123 * location/camera/micrphone. 124 */ getMediaSessionCallbackFgsWhileInUseTempAllowDurationMs()125 public static long getMediaSessionCallbackFgsWhileInUseTempAllowDurationMs() { 126 return sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs; 127 } 128 129 /** 130 * Returns the duration (in milliseconds) that a media session can remain in an engaged state, 131 * where it is only considered engaged if transitioning from active playback. After this 132 * duration, the session is disengaged until explicit user action triggers active playback. 133 */ getMediaSessionTempUserEngagedDurationMs()134 public static long getMediaSessionTempUserEngagedDurationMs() { 135 return sMediaSessionTempUserEngagedDurationMs; 136 } 137 dump(PrintWriter pw, String prefix)138 public static void dump(PrintWriter pw, String prefix) { 139 pw.println("Media session config:"); 140 final String dumpFormat = prefix + " %s: [cur: %s, def: %s]"; 141 pw.println(TextUtils.formatSimple(dumpFormat, 142 KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS, 143 sMediaButtonReceiverFgsAllowlistDurationMs, 144 DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS)); 145 pw.println(TextUtils.formatSimple(dumpFormat, 146 KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS, 147 sMediaSessionCallbackFgsAllowlistDurationMs, 148 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS)); 149 pw.println(TextUtils.formatSimple(dumpFormat, 150 KEY_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS, 151 sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs, 152 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS)); 153 pw.println(TextUtils.formatSimple(dumpFormat, 154 KEY_MEDIA_SESSION_TEMP_USER_ENGAGED_DURATION_MS, 155 sMediaSessionTempUserEngagedDurationMs, 156 DEFAULT_MEDIA_SESSION_TEMP_USER_ENGAGED_DURATION_MS)); 157 } 158 } 159