1 /*
2  * Copyright (C) 2023 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.contentprotection;
18 
19 import android.annotation.NonNull;
20 import android.annotation.UserIdInt;
21 import android.app.admin.DevicePolicyManagerInternal;
22 import android.content.ContentResolver;
23 import android.database.ContentObserver;
24 import android.net.Uri;
25 import android.os.Handler;
26 import android.os.UserHandle;
27 import android.provider.Settings;
28 import android.util.Slog;
29 
30 import com.android.internal.annotations.VisibleForTesting;
31 
32 /**
33  * Manages consent for content protection.
34  *
35  * @hide
36  */
37 public class ContentProtectionConsentManager {
38 
39     private static final String TAG = "ContentProtectionConsentManager";
40 
41     private static final String KEY_PACKAGE_VERIFIER_USER_CONSENT = "package_verifier_user_consent";
42 
43     @NonNull private final ContentResolver mContentResolver;
44 
45     @NonNull private final DevicePolicyManagerInternal mDevicePolicyManagerInternal;
46 
47     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
48     @NonNull
49     public final ContentObserver mContentObserver;
50 
51     private volatile boolean mCachedPackageVerifierConsent;
52 
ContentProtectionConsentManager( @onNull Handler handler, @NonNull ContentResolver contentResolver, @NonNull DevicePolicyManagerInternal devicePolicyManagerInternal)53     public ContentProtectionConsentManager(
54             @NonNull Handler handler,
55             @NonNull ContentResolver contentResolver,
56             @NonNull DevicePolicyManagerInternal devicePolicyManagerInternal) {
57         mContentResolver = contentResolver;
58         mDevicePolicyManagerInternal = devicePolicyManagerInternal;
59         mContentObserver = new SettingsObserver(handler);
60 
61         contentResolver.registerContentObserver(
62                 Settings.Global.getUriFor(KEY_PACKAGE_VERIFIER_USER_CONSENT),
63                 /* notifyForDescendants= */ false,
64                 mContentObserver,
65                 UserHandle.USER_ALL);
66         mCachedPackageVerifierConsent = isPackageVerifierConsentGranted();
67     }
68 
69     /**
70      * Returns true if all the consents are granted
71      */
isConsentGranted(@serIdInt int userId)72     public boolean isConsentGranted(@UserIdInt int userId) {
73         return mCachedPackageVerifierConsent && !isUserOrganizationManaged(userId);
74     }
75 
isPackageVerifierConsentGranted()76     private boolean isPackageVerifierConsentGranted() {
77         // Not always cached internally
78         return Settings.Global.getInt(
79                         mContentResolver, KEY_PACKAGE_VERIFIER_USER_CONSENT, /* def= */ 0)
80                 >= 1;
81     }
82 
isUserOrganizationManaged(@serIdInt int userId)83     private boolean isUserOrganizationManaged(@UserIdInt int userId) {
84         // Cached internally
85         return mDevicePolicyManagerInternal.isUserOrganizationManaged(userId);
86     }
87 
88     private final class SettingsObserver extends ContentObserver {
89 
SettingsObserver(Handler handler)90         SettingsObserver(Handler handler) {
91             super(handler);
92         }
93 
94         @Override
onChange(boolean selfChange, Uri uri, @UserIdInt int userId)95         public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
96             final String property = uri.getLastPathSegment();
97             if (property == null) {
98                 return;
99             }
100             switch (property) {
101                 case KEY_PACKAGE_VERIFIER_USER_CONSENT:
102                     mCachedPackageVerifierConsent = isPackageVerifierConsentGranted();
103                     return;
104                 default:
105                     Slog.w(TAG, "Ignoring unexpected property: " + property);
106             }
107         }
108     }
109 }
110