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      * Denotes the duration for which an app receiving a media session callback and the FGS started
51      * there can be temporarily allowed to have while-in-use permissions such as
52      * location/camera/microphone for a duration of time.
53      */
54     private static final String KEY_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS =
55             "media_session_callback_fgs_while_in_use_temp_allow_duration_ms";
56     private static final long DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS
57             = 10_000;
58     private static volatile long sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs =
59             DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS;
60 
refresh(DeviceConfig.Properties properties)61     private static void refresh(DeviceConfig.Properties properties) {
62         final Set<String> keys = properties.getKeyset();
63         properties.getKeyset().forEach(key -> {
64             switch (key) {
65                 case KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS:
66                     sMediaButtonReceiverFgsAllowlistDurationMs = properties.getLong(key,
67                             DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS);
68                     break;
69                 case KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS:
70                     sMediaSessionCallbackFgsAllowlistDurationMs = properties.getLong(key,
71                             DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS);
72                     break;
73                 case KEY_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS:
74                     sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs = properties.getLong(key,
75                             DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS);
76             }
77         });
78     }
79 
initialize(Context context)80     public static void initialize(Context context) {
81         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_MEDIA,
82                 context.getMainExecutor(), properties -> refresh(properties));
83         refresh(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_MEDIA));
84     }
85 
86     /**
87      * Returns the duration for which a media button receiver will be exempted from
88      * FGS-from-BG restriction and so will be allowed to start an FGS even if it is in the
89      * background state while it receives a media key event.
90      */
getMediaButtonReceiverFgsAllowlistDurationMs()91     public static long getMediaButtonReceiverFgsAllowlistDurationMs() {
92         return sMediaButtonReceiverFgsAllowlistDurationMs;
93     }
94 
95     /**
96      * Returns the duration for which an app receiving a media session callback will be
97      * exempted from FGS-from-BG restriction and so will be allowed to start an FGS even if
98      * it is in the background state while it receives a media session callback.
99      */
getMediaSessionCallbackFgsAllowlistDurationMs()100     public static long getMediaSessionCallbackFgsAllowlistDurationMs() {
101         return sMediaSessionCallbackFgsAllowlistDurationMs;
102     }
103 
104     /**
105      * Return the duration for which an app receiving a media session callback and the FGS started
106      * there can be temporarily allowed to have while-in-use permissions such as
107      * location/camera/micrphone.
108      */
getMediaSessionCallbackFgsWhileInUseTempAllowDurationMs()109     public static long getMediaSessionCallbackFgsWhileInUseTempAllowDurationMs() {
110         return sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs;
111     }
112 
dump(PrintWriter pw, String prefix)113     public static void dump(PrintWriter pw, String prefix) {
114         pw.println("Media session config:");
115         final String dumpFormat = prefix + "  %s: [cur: %s, def: %s]";
116         pw.println(TextUtils.formatSimple(dumpFormat,
117                 KEY_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS,
118                 sMediaButtonReceiverFgsAllowlistDurationMs,
119                 DEFAULT_MEDIA_BUTTON_RECEIVER_FGS_ALLOWLIST_DURATION_MS));
120         pw.println(TextUtils.formatSimple(dumpFormat,
121                 KEY_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS,
122                 sMediaSessionCallbackFgsAllowlistDurationMs,
123                 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_ALLOWLIST_DURATION_MS));
124         pw.println(TextUtils.formatSimple(dumpFormat,
125                 KEY_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS,
126                 sMediaSessionCallbackFgsWhileInUseTempAllowDurationMs,
127                 DEFAULT_MEDIA_SESSION_CALLBACK_FGS_WHILE_IN_USE_TEMP_ALLOW_DURATION_MS));
128     }
129 }
130