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