1 /*
2  * Copyright (C) 2018 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.system;
18 
19 import android.app.ActivityManager;
20 import android.app.AppOpsManager;
21 import android.app.INotificationManager;
22 import android.content.Context;
23 import android.content.pm.ApplicationInfo;
24 import android.content.pm.IPackageManager;
25 import android.content.pm.PackageManager;
26 import android.os.AsyncTask;
27 import android.os.Bundle;
28 import android.os.IBinder;
29 import android.os.RemoteException;
30 import android.os.ServiceManager;
31 import android.os.UserHandle;
32 import android.os.UserManager;
33 import android.widget.Toast;
34 
35 import androidx.annotation.VisibleForTesting;
36 import androidx.annotation.XmlRes;
37 
38 import com.android.car.settings.R;
39 import com.android.car.settings.common.Logger;
40 import com.android.car.settings.common.SettingsFragment;
41 import com.android.car.ui.toolbar.MenuItem;
42 import com.android.settingslib.RestrictedLockUtils;
43 import com.android.settingslib.RestrictedLockUtilsInternal;
44 
45 import java.lang.ref.WeakReference;
46 import java.util.Collections;
47 import java.util.List;
48 
49 /**
50  * Presents the user with information about resetting app preferences.
51  */
52 public class ResetAppPrefFragment extends SettingsFragment {
53 
54     private static final Logger LOG = new Logger(ResetAppPrefFragment.class);
55 
56     private MenuItem mResetButton;
57     @VisibleForTesting
58     AsyncTask<Void, Void, Void> mResetTask;
59 
60     @Override
61     @XmlRes
getPreferenceScreenResId()62     protected int getPreferenceScreenResId() {
63         return R.xml.reset_app_pref_fragment;
64     }
65 
66     @Override
getToolbarMenuItems()67     public List<MenuItem> getToolbarMenuItems() {
68         return Collections.singletonList(mResetButton);
69     }
70 
71     @Override
onCreate(Bundle savedInstanceState)72     public void onCreate(Bundle savedInstanceState) {
73         super.onCreate(savedInstanceState);
74 
75         mResetButton = new MenuItem.Builder(getContext())
76                 .setTitle(R.string.reset_app_pref_button_text)
77                 .setOnClickListener(i -> resetAppPreferencesIfAllowed())
78                 .build();
79     }
80 
resetAppPreferencesIfAllowed()81     private void resetAppPreferencesIfAllowed() {
82         if (getActivity() == null) {
83             LOG.w("Unable to reset app preferences. Null activity");
84             return;
85         }
86         boolean appsControlDisallowedBySystem =
87                 RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
88                         UserManager.DISALLOW_APPS_CONTROL, UserHandle.myUserId());
89         RestrictedLockUtils.EnforcedAdmin appsControlDisallowedAdmin =
90                 RestrictedLockUtilsInternal.checkIfRestrictionEnforced(getActivity(),
91                         UserManager.DISALLOW_APPS_CONTROL, UserHandle.myUserId());
92         if (appsControlDisallowedAdmin != null && !appsControlDisallowedBySystem) {
93             RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
94                     getActivity(), appsControlDisallowedAdmin);
95         } else {
96             resetAppPreferences();
97         }
98     }
99 
resetAppPreferences()100     private void resetAppPreferences() {
101         mResetTask = new ResetTask(requireContext().getApplicationContext());
102         mResetTask.execute();
103     }
104 
105     private static class ResetTask extends AsyncTask<Void, Void, Void> {
106 
107         private final WeakReference<Context> mContext;
108 
ResetTask(Context context)109         ResetTask(Context context) {
110             mContext = new WeakReference<>(context);
111         }
112 
113         @Override
doInBackground(Void... unused)114         protected Void doInBackground(Void... unused) {
115             Context context = mContext.get();
116             if (context == null) {
117                 LOG.w("Unable to reset app preferences. Null context");
118                 return null;
119             }
120             PackageManager packageManager = context.getPackageManager();
121             IBinder notificationManagerServiceBinder = ServiceManager.getService(
122                     Context.NOTIFICATION_SERVICE);
123             if (notificationManagerServiceBinder == null) {
124                 LOG.w("Unable to reset app preferences. Null notification manager service");
125                 return null;
126             }
127             INotificationManager notificationManagerService =
128                     INotificationManager.Stub.asInterface(notificationManagerServiceBinder);
129 
130             // Reset app notifications.
131             // Reset disabled apps.
132             List<ApplicationInfo> apps = packageManager.getInstalledApplications(
133                     PackageManager.MATCH_DISABLED_COMPONENTS);
134             for (ApplicationInfo app : apps) {
135                 try {
136                     notificationManagerService.setNotificationsEnabledForPackage(
137                             app.packageName,
138                             app.uid, true);
139                 } catch (RemoteException e) {
140                     LOG.w("Unable to reset notification preferences for app: " + app.name, e);
141                 }
142                 if (!app.enabled) {
143                     if (packageManager.getApplicationEnabledSetting(app.packageName)
144                             == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
145                         packageManager.setApplicationEnabledSetting(app.packageName,
146                                 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
147                                 PackageManager.DONT_KILL_APP);
148                     }
149                 }
150             }
151 
152             // Reset default applications for actions.
153             // Reset background data restrictions for apps.
154             // Reset permission restrictions.
155             try {
156                 IBinder packageManagerServiceBinder = ServiceManager.getService("package");
157                 if (packageManagerServiceBinder == null) {
158                     LOG.w("Unable to reset app preferences. Null package manager service");
159                     return null;
160                 }
161                 IPackageManager.Stub.asInterface(
162                         packageManagerServiceBinder).resetApplicationPreferences(
163                         ActivityManager.getCurrentUser());
164             } catch (RemoteException e) {
165                 LOG.w("Unable to reset app preferences", e);
166             }
167 
168             // Cleanup.
169             context.getSystemService(AppOpsManager.class).resetAllModes();
170 
171             return null;
172         }
173 
174         @Override
onPostExecute(Void unused)175         protected void onPostExecute(Void unused) {
176             super.onPostExecute(unused);
177             Context context = mContext.get();
178             if (context != null) {
179                 Toast.makeText(context, R.string.reset_app_pref_complete_toast,
180                         Toast.LENGTH_SHORT).show();
181             }
182         }
183     }
184 }
185