1 /*
2  * Copyright (C) 2019 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.car.settings.applications.managedomainurls;
18 
19 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
20 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
21 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
22 
23 import android.car.drivingstate.CarUxRestrictions;
24 import android.content.Context;
25 import android.content.pm.ApplicationInfo;
26 import android.content.pm.PackageManager;
27 
28 import androidx.preference.ListPreference;
29 
30 import com.android.car.settings.R;
31 import com.android.car.settings.common.FragmentController;
32 import com.android.car.settings.common.Logger;
33 
34 /**
35  * Business logic to define how the app should handle related domain links (whether related domain
36  * links should be opened always, never, or after asking).
37  */
38 public class AppLinkStatePreferenceController extends
39         AppLaunchSettingsBasePreferenceController<ListPreference> {
40 
41     private static final Logger LOG = new Logger(AppLinkStatePreferenceController.class);
42 
43     private final PackageManager mPm;
44     private boolean mHasDomainUrls;
45 
AppLinkStatePreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)46     public AppLinkStatePreferenceController(Context context, String preferenceKey,
47             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
48         super(context, preferenceKey, fragmentController, uxRestrictions);
49         mPm = context.getPackageManager();
50     }
51 
52     @Override
getPreferenceType()53     protected Class<ListPreference> getPreferenceType() {
54         return ListPreference.class;
55     }
56 
57     @Override
onCreateInternal()58     protected void onCreateInternal() {
59         mHasDomainUrls =
60                 (getAppEntry().info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS)
61                         != 0;
62     }
63 
64     @Override
updateState(ListPreference preference)65     protected void updateState(ListPreference preference) {
66         if (isBrowserApp()) {
67             preference.setEnabled(false);
68         } else {
69             preference.setEnabled(mHasDomainUrls);
70 
71             preference.setEntries(new CharSequence[]{
72                     getContext().getString(R.string.app_link_open_always),
73                     getContext().getString(R.string.app_link_open_ask),
74                     getContext().getString(R.string.app_link_open_never),
75             });
76             preference.setEntryValues(new CharSequence[]{
77                     Integer.toString(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS),
78                     Integer.toString(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK),
79                     Integer.toString(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER),
80             });
81 
82             if (mHasDomainUrls) {
83                 int state = mPm.getIntentVerificationStatusAsUser(getPackageName(),
84                         getCurrentUserId());
85                 preference.setValueIndex(linkStateToIndex(state));
86             }
87         }
88     }
89 
90     @Override
handlePreferenceChanged(ListPreference preference, Object newValue)91     protected boolean handlePreferenceChanged(ListPreference preference, Object newValue) {
92         if (isBrowserApp()) {
93             // We shouldn't get into this state, but if we do make sure
94             // not to cause any permanent mayhem.
95             return false;
96         }
97 
98         int newState = Integer.parseInt((String) newValue);
99         int priorState = mPm.getIntentVerificationStatusAsUser(getPackageName(),
100                 getCurrentUserId());
101         if (priorState == newState) {
102             return false;
103         }
104 
105         boolean success = mPm.updateIntentVerificationStatusAsUser(getPackageName(), newState,
106                 getCurrentUserId());
107         if (success) {
108             // Read back the state to see if the change worked.
109             int updatedState = mPm.getIntentVerificationStatusAsUser(getPackageName(),
110                     getCurrentUserId());
111             success = (newState == updatedState);
112         } else {
113             LOG.e("Couldn't update intent verification status!");
114         }
115         return success;
116     }
117 
linkStateToIndex(int state)118     private int linkStateToIndex(int state) {
119         switch (state) {
120             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
121                 return getPreference().findIndexOfValue(
122                         Integer.toString(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS));
123             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER:
124                 return getPreference().findIndexOfValue(
125                         Integer.toString(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER));
126             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK:
127             default:
128                 return getPreference().findIndexOfValue(
129                         Integer.toString(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK));
130         }
131     }
132 }
133