1 /* 2 * Copyright (C) 2016 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.settings.applications; 16 17 import android.annotation.Nullable; 18 import android.app.Application; 19 import android.content.Context; 20 import android.os.Bundle; 21 import android.support.v7.preference.DropDownPreference; 22 import android.support.v7.preference.Preference; 23 import android.support.v7.preference.Preference.OnPreferenceChangeListener; 24 import android.support.v7.preference.PreferenceScreen; 25 import android.support.v7.preference.PreferenceViewHolder; 26 import android.view.View; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.internal.logging.nano.MetricsProto; 30 import com.android.internal.telephony.SmsUsageMonitor; 31 import com.android.settings.R; 32 import com.android.settings.applications.AppStateBaseBridge.Callback; 33 import com.android.settings.applications.AppStateSmsPremBridge.SmsState; 34 import com.android.settings.notification.EmptyTextSettings; 35 import com.android.settings.overlay.FeatureFactory; 36 import com.android.settingslib.applications.ApplicationsState; 37 import com.android.settingslib.applications.ApplicationsState.AppEntry; 38 import com.android.settingslib.applications.ApplicationsState.Callbacks; 39 import com.android.settingslib.applications.ApplicationsState.Session; 40 import com.android.settingslib.widget.FooterPreference; 41 42 import java.util.ArrayList; 43 44 public class PremiumSmsAccess extends EmptyTextSettings implements Callback, Callbacks, OnPreferenceChangeListener { 45 46 private ApplicationsState mApplicationsState; 47 private AppStateSmsPremBridge mSmsBackend; 48 private Session mSession; 49 50 @Override onCreate(Bundle icicle)51 public void onCreate(Bundle icicle) { 52 super.onCreate(icicle); 53 mApplicationsState = ApplicationsState.getInstance((Application) 54 getContext().getApplicationContext()); 55 mSession = mApplicationsState.newSession(this, getLifecycle()); 56 mSmsBackend = new AppStateSmsPremBridge(getContext(), mApplicationsState, this); 57 } 58 59 @Override onViewCreated(View view, @Nullable Bundle savedInstanceState)60 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 61 super.onViewCreated(view, savedInstanceState); 62 setLoading(true, false); 63 } 64 65 @Override onResume()66 public void onResume() { 67 super.onResume(); 68 mSmsBackend.resume(); 69 } 70 71 @Override onPause()72 public void onPause() { 73 mSmsBackend.pause(); 74 super.onPause(); 75 } 76 77 @Override onDestroy()78 public void onDestroy() { 79 mSmsBackend.release(); 80 super.onDestroy(); 81 } 82 83 @Override getPreferenceScreenResId()84 protected int getPreferenceScreenResId() { 85 return R.xml.premium_sms_settings; 86 } 87 88 @Override getMetricsCategory()89 public int getMetricsCategory() { 90 return MetricsProto.MetricsEvent.PREMIUM_SMS_ACCESS; 91 } 92 93 @Override onPreferenceChange(Preference preference, Object newValue)94 public boolean onPreferenceChange(Preference preference, Object newValue) { 95 PremiumSmsPreference pref = (PremiumSmsPreference) preference; 96 int smsState = Integer.parseInt((String) newValue); 97 logSpecialPermissionChange(smsState, pref.mAppEntry.info.packageName); 98 mSmsBackend.setSmsState(pref.mAppEntry.info.packageName, smsState); 99 return true; 100 } 101 102 @VisibleForTesting logSpecialPermissionChange(int smsState, String packageName)103 void logSpecialPermissionChange(int smsState, String packageName) { 104 int category = SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN; 105 switch (smsState) { 106 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER: 107 category = MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_PREMIUM_SMS_ASK; 108 break; 109 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW: 110 category = MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_PREMIUM_SMS_DENY; 111 break; 112 case SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW: 113 category = MetricsProto.MetricsEvent. 114 APP_SPECIAL_PERMISSION_PREMIUM_SMS_ALWAYS_ALLOW; 115 break; 116 } 117 if (category != SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) { 118 FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider().action( 119 getContext(), category, packageName); 120 } 121 } 122 updatePrefs(ArrayList<AppEntry> apps)123 private void updatePrefs(ArrayList<AppEntry> apps) { 124 if (apps == null) return; 125 setEmptyText(R.string.premium_sms_none); 126 setLoading(false, true); 127 final PreferenceScreen screen = getPreferenceScreen(); 128 screen.removeAll(); 129 screen.setOrderingAsAdded(true); 130 131 for (int i = 0; i < apps.size(); i++) { 132 final PremiumSmsPreference smsPreference = 133 new PremiumSmsPreference(apps.get(i), getPrefContext()); 134 smsPreference.setOnPreferenceChangeListener(this); 135 screen.addPreference(smsPreference); 136 } 137 if (apps.size() != 0) { 138 FooterPreference footer = new FooterPreference(getPrefContext()); 139 footer.setTitle(R.string.premium_sms_warning); 140 screen.addPreference(footer); 141 } 142 } 143 update()144 private void update() { 145 updatePrefs(mSession.rebuild(AppStateSmsPremBridge.FILTER_APP_PREMIUM_SMS, 146 ApplicationsState.ALPHA_COMPARATOR)); 147 } 148 149 @Override onExtraInfoUpdated()150 public void onExtraInfoUpdated() { 151 update(); 152 } 153 154 @Override onRebuildComplete(ArrayList<AppEntry> apps)155 public void onRebuildComplete(ArrayList<AppEntry> apps) { 156 updatePrefs(apps); 157 } 158 159 @Override onRunningStateChanged(boolean running)160 public void onRunningStateChanged(boolean running) { 161 162 } 163 164 @Override onPackageListChanged()165 public void onPackageListChanged() { 166 167 } 168 169 @Override onPackageIconChanged()170 public void onPackageIconChanged() { 171 172 } 173 174 @Override onPackageSizeChanged(String packageName)175 public void onPackageSizeChanged(String packageName) { 176 177 } 178 179 @Override onAllSizesComputed()180 public void onAllSizesComputed() { 181 182 } 183 184 @Override onLauncherInfoChanged()185 public void onLauncherInfoChanged() { 186 187 } 188 189 @Override onLoadEntriesCompleted()190 public void onLoadEntriesCompleted() { 191 192 } 193 194 private class PremiumSmsPreference extends DropDownPreference { 195 private final AppEntry mAppEntry; 196 PremiumSmsPreference(AppEntry appEntry, Context context)197 public PremiumSmsPreference(AppEntry appEntry, Context context) { 198 super(context); 199 mAppEntry = appEntry; 200 mAppEntry.ensureLabel(context); 201 setTitle(mAppEntry.label); 202 if (mAppEntry.icon != null) { 203 setIcon(mAppEntry.icon); 204 } 205 setEntries(R.array.security_settings_premium_sms_values); 206 setEntryValues(new CharSequence[] { 207 String.valueOf(SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ASK_USER), 208 String.valueOf(SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW), 209 String.valueOf(SmsUsageMonitor.PREMIUM_SMS_PERMISSION_ALWAYS_ALLOW), 210 }); 211 setValue(String.valueOf(getCurrentValue())); 212 setSummary("%s"); 213 } 214 getCurrentValue()215 private int getCurrentValue() { 216 return mAppEntry.extraInfo instanceof SmsState 217 ? ((SmsState) mAppEntry.extraInfo).smsState 218 : SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN; 219 } 220 221 @Override onBindViewHolder(PreferenceViewHolder holder)222 public void onBindViewHolder(PreferenceViewHolder holder) { 223 if (getIcon() == null) { 224 holder.itemView.post(new Runnable() { 225 @Override 226 public void run() { 227 mApplicationsState.ensureIcon(mAppEntry); 228 setIcon(mAppEntry.icon); 229 } 230 }); 231 } 232 super.onBindViewHolder(holder); 233 } 234 } 235 } 236