• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 package com.android.settings.applications.appinfo;
17 
18 import static android.app.Activity.RESULT_CANCELED;
19 import static android.app.Activity.RESULT_OK;
20 
21 import android.app.AppOpsManager;
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 import android.os.Bundle;
25 
26 import androidx.appcompat.app.AlertDialog;
27 import androidx.preference.Preference;
28 import androidx.preference.Preference.OnPreferenceChangeListener;
29 
30 import com.android.settings.R;
31 import com.android.settings.Settings;
32 import com.android.settings.applications.AppInfoWithHeader;
33 import com.android.settings.applications.AppStateAlarmsAndRemindersBridge;
34 import com.android.settingslib.RestrictedSwitchPreference;
35 import com.android.settingslib.applications.ApplicationsState.AppEntry;
36 
37 /**
38  * App specific activity to show details about
39  * {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM}.
40  */
41 public class AlarmsAndRemindersDetails extends AppInfoWithHeader
42         implements OnPreferenceChangeListener {
43 
44     private static final String KEY_SWITCH = "alarms_and_reminders_switch";
45     private static final String UNCOMMITTED_STATE_KEY = "uncommitted_state";
46 
47     private AppStateAlarmsAndRemindersBridge mAppBridge;
48     private AppOpsManager mAppOpsManager;
49     private RestrictedSwitchPreference mSwitchPref;
50     private AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState mPermissionState;
51     private volatile Boolean mUncommittedState;
52 
53     /**
54      * Returns the string that states whether the app has access to
55      * {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM}.
56      */
getSummary(Context context, AppEntry entry)57     public static CharSequence getSummary(Context context, AppEntry entry) {
58         final AppStateAlarmsAndRemindersBridge.AlarmsAndRemindersState state =
59                 new AppStateAlarmsAndRemindersBridge(context, /*appState=*/null,
60                         /*callback=*/null).createPermissionState(entry.info.packageName,
61                         entry.info.uid);
62 
63         return context.getString(state.isAllowed() ? R.string.app_permission_summary_allowed
64                 : R.string.app_permission_summary_not_allowed);
65     }
66 
67     @Override
onCreate(Bundle savedInstanceState)68     public void onCreate(Bundle savedInstanceState) {
69         super.onCreate(savedInstanceState);
70 
71         final Context context = getActivity();
72         mAppBridge = new AppStateAlarmsAndRemindersBridge(context, mState, /*callback=*/null);
73         mAppOpsManager = context.getSystemService(AppOpsManager.class);
74 
75         if (savedInstanceState != null) {
76             mUncommittedState = (Boolean) savedInstanceState.get(UNCOMMITTED_STATE_KEY);
77             if (mUncommittedState != null && isAppSpecific()) {
78                 setResult(mUncommittedState ? RESULT_OK : RESULT_CANCELED);
79             }
80         }
81         addPreferencesFromResource(R.xml.alarms_and_reminders);
82         mSwitchPref = findPreference(KEY_SWITCH);
83         mSwitchPref.setOnPreferenceChangeListener(this);
84     }
85 
86     @Override
onSaveInstanceState(Bundle outState)87     public void onSaveInstanceState(Bundle outState) {
88         super.onSaveInstanceState(outState);
89         if (mUncommittedState != null) {
90             outState.putObject(UNCOMMITTED_STATE_KEY, mUncommittedState);
91         }
92     }
93 
94     @Override
onPreferenceChange(Preference preference, Object newValue)95     public boolean onPreferenceChange(Preference preference, Object newValue) {
96         if (preference == mSwitchPref) {
97             mUncommittedState = (Boolean) newValue;
98             if (isAppSpecific()) {
99                 setResult(mUncommittedState ? RESULT_OK : RESULT_CANCELED);
100             }
101             refreshUi();
102             return true;
103         }
104         return false;
105     }
106 
setCanScheduleAlarms(boolean newState)107     private void setCanScheduleAlarms(boolean newState) {
108         final int uid = mPackageInfo.applicationInfo.uid;
109         mAppOpsManager.setUidMode(AppOpsManager.OPSTR_SCHEDULE_EXACT_ALARM, uid,
110                 newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_ERRORED);
111     }
112 
logPermissionChange(boolean newState, String packageName)113     private void logPermissionChange(boolean newState, String packageName) {
114         mMetricsFeatureProvider.action(
115                 mMetricsFeatureProvider.getAttribution(getActivity()),
116                 SettingsEnums.ACTION_ALARMS_AND_REMINDERS_TOGGLE,
117                 getMetricsCategory(),
118                 packageName,
119                 newState ? 1 : 0);
120     }
121 
isAppSpecific()122     private boolean isAppSpecific() {
123         return Settings.AlarmsAndRemindersAppActivity.class.getName().equals(
124                 getIntent().getComponent().getClassName());
125     }
126 
127     @Override
onPause()128     public void onPause() {
129         super.onPause();
130         if (getActivity().isChangingConfigurations()) {
131             return;
132         }
133         if (mPermissionState != null && mUncommittedState != null
134                 && mUncommittedState != mPermissionState.isAllowed()) {
135             setCanScheduleAlarms(mUncommittedState);
136             logPermissionChange(mUncommittedState, mPackageName);
137             mUncommittedState = null;
138         }
139     }
140 
141     @Override
refreshUi()142     protected boolean refreshUi() {
143         if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
144             return false;
145         }
146         mPermissionState = mAppBridge.createPermissionState(mPackageName,
147                 mPackageInfo.applicationInfo.uid);
148         mSwitchPref.setEnabled(mPermissionState.shouldBeVisible());
149         mSwitchPref.setChecked(
150                 mUncommittedState != null ? mUncommittedState : mPermissionState.isAllowed());
151         return true;
152     }
153 
154     @Override
createDialog(int id, int errorCode)155     protected AlertDialog createDialog(int id, int errorCode) {
156         return null;
157     }
158 
159     @Override
getMetricsCategory()160     public int getMetricsCategory() {
161         return SettingsEnums.ALARMS_AND_REMINDERS;
162     }
163 }
164