1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.car.developeroptions.development.autofill;
16 
17 import android.content.ContentResolver;
18 import android.content.Context;
19 import android.database.ContentObserver;
20 import android.net.Uri;
21 import android.os.Handler;
22 import android.os.Looper;
23 import android.provider.Settings;
24 import android.util.AttributeSet;
25 import android.util.Log;
26 import android.view.autofill.AutofillManager;
27 
28 import androidx.preference.PreferenceCategory;
29 
30 public final class AutofillPreferenceCategory extends PreferenceCategory {
31 
32     private static final String TAG = "AutofillPreferenceCategory";
33     private static final long DELAYED_MESSAGE_TIME_MS = 2000;
34 
35     private final ContentResolver mContentResolver;
36     private final ContentObserver mSettingsObserver;
37     private final Handler mHandler = new Handler(Looper.getMainLooper());
38 
AutofillPreferenceCategory(Context context, AttributeSet attrs)39     public AutofillPreferenceCategory(Context context, AttributeSet attrs) {
40         super(context, attrs);
41 
42         mSettingsObserver = new ContentObserver(mHandler) {
43             @Override
44             public void onChange(boolean selfChange, Uri uri, int userId) {
45                 // We cannot apply the change yet because AutofillManager.isEnabled() state is
46                 // updated by a ContentObserver as well and there's no guarantee of which observer
47                 // is called first - hence, it's possible that the state didn't change here yet.
48                 mHandler.postDelayed(() -> notifyDependencyChange(shouldDisableDependents()),
49                         DELAYED_MESSAGE_TIME_MS);
50             }
51         };
52         mContentResolver = context.getContentResolver();
53     }
54 
55     @Override
onAttached()56     public void onAttached() {
57         super.onAttached();
58 
59         mContentResolver.registerContentObserver(
60                 Settings.Secure.getUriFor(Settings.Secure.AUTOFILL_SERVICE), false,
61                 mSettingsObserver);
62     }
63 
64     @Override
onDetached()65     public void onDetached() {
66         mContentResolver.unregisterContentObserver(mSettingsObserver);
67 
68         super.onDetached();
69     }
70 
71     // PreferenceCategory.isEnabled() always return false, so we rather not change that logic
72     // decide whether the children should be shown using isAutofillEnabled() instead.
isAutofillEnabled()73     private boolean isAutofillEnabled() {
74         final AutofillManager afm = getContext().getSystemService(AutofillManager.class);
75         final boolean enabled = afm != null && afm.isEnabled();
76         Log.v(TAG, "isAutofillEnabled(): " + enabled);
77         return enabled;
78     }
79 
80     @Override
shouldDisableDependents()81     public boolean shouldDisableDependents() {
82         final boolean shouldIt = !isAutofillEnabled();
83         Log.v(TAG, "shouldDisableDependents(): " + shouldIt);
84         return shouldIt;
85     }
86 }
87