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