Home | History | Annotate | Download | only in notification
      1 /*
      2  * Copyright (C) 2014 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.settings.notification;
     18 
     19 import android.content.Context;
     20 import android.content.Intent;
     21 import android.content.pm.PackageInfo;
     22 import android.content.pm.PackageManager;
     23 import android.content.pm.PackageManager.NameNotFoundException;
     24 import android.os.Bundle;
     25 import android.preference.Preference;
     26 import android.preference.Preference.OnPreferenceChangeListener;
     27 import android.preference.SwitchPreference;
     28 import android.provider.Settings;
     29 import android.text.TextUtils;
     30 import android.util.ArrayMap;
     31 import android.util.Log;
     32 import android.view.View;
     33 import android.view.View.OnClickListener;
     34 import android.view.ViewGroup;
     35 import android.widget.ImageView;
     36 import android.widget.TextView;
     37 import android.widget.Toast;
     38 
     39 import com.android.internal.widget.LockPatternUtils;
     40 import com.android.settings.R;
     41 import com.android.settings.SettingsPreferenceFragment;
     42 import com.android.settings.Utils;
     43 import com.android.settings.notification.NotificationAppList.AppRow;
     44 import com.android.settings.notification.NotificationAppList.Backend;
     45 
     46 /** These settings are per app, so should not be returned in global search results. */
     47 public class AppNotificationSettings extends SettingsPreferenceFragment {
     48     private static final String TAG = "AppNotificationSettings";
     49     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     50 
     51     private static final String KEY_BLOCK = "block";
     52     private static final String KEY_PRIORITY = "priority";
     53     private static final String KEY_SENSITIVE = "sensitive";
     54 
     55     static final String EXTRA_HAS_SETTINGS_INTENT = "has_settings_intent";
     56     static final String EXTRA_SETTINGS_INTENT = "settings_intent";
     57 
     58     private final Backend mBackend = new Backend();
     59 
     60     private Context mContext;
     61     private SwitchPreference mBlock;
     62     private SwitchPreference mPriority;
     63     private SwitchPreference mSensitive;
     64     private AppRow mAppRow;
     65     private boolean mCreated;
     66 
     67     @Override
     68     public void onActivityCreated(Bundle savedInstanceState) {
     69         super.onActivityCreated(savedInstanceState);
     70         if (DEBUG) Log.d(TAG, "onActivityCreated mCreated=" + mCreated);
     71         if (mCreated) {
     72             Log.w(TAG, "onActivityCreated: ignoring duplicate call");
     73             return;
     74         }
     75         mCreated = true;
     76         if (mAppRow == null) return;
     77         final View content = getActivity().findViewById(R.id.main_content);
     78         final ViewGroup contentParent = (ViewGroup) content.getParent();
     79         final View bar = getActivity().getLayoutInflater().inflate(R.layout.app_notification_header,
     80                 contentParent, false);
     81 
     82         final ImageView appIcon = (ImageView) bar.findViewById(R.id.app_icon);
     83         appIcon.setImageDrawable(mAppRow.icon);
     84 
     85         final TextView appName = (TextView) bar.findViewById(R.id.app_name);
     86         appName.setText(mAppRow.label);
     87 
     88         final View appSettings = bar.findViewById(R.id.app_settings);
     89         if (mAppRow.settingsIntent == null) {
     90             appSettings.setVisibility(View.GONE);
     91         } else {
     92             appSettings.setClickable(true);
     93             appSettings.setOnClickListener(new OnClickListener() {
     94                 @Override
     95                 public void onClick(View v) {
     96                     mContext.startActivity(mAppRow.settingsIntent);
     97                 }
     98             });
     99         }
    100         contentParent.addView(bar, 0);
    101     }
    102 
    103     @Override
    104     public void onCreate(Bundle savedInstanceState) {
    105         super.onCreate(savedInstanceState);
    106         mContext = getActivity();
    107         Intent intent = getActivity().getIntent();
    108         if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent);
    109         if (intent == null) {
    110             Log.w(TAG, "No intent");
    111             toastAndFinish();
    112             return;
    113         }
    114 
    115         final int uid = intent.getIntExtra(Settings.EXTRA_APP_UID, -1);
    116         final String pkg = intent.getStringExtra(Settings.EXTRA_APP_PACKAGE);
    117         if (uid == -1 || TextUtils.isEmpty(pkg)) {
    118             Log.w(TAG, "Missing extras: " + Settings.EXTRA_APP_PACKAGE + " was " + pkg + ", "
    119                     + Settings.EXTRA_APP_UID + " was " + uid);
    120             toastAndFinish();
    121             return;
    122         }
    123 
    124         if (DEBUG) Log.d(TAG, "Load details for pkg=" + pkg + " uid=" + uid);
    125         final PackageManager pm = getPackageManager();
    126         final PackageInfo info = findPackageInfo(pm, pkg, uid);
    127         if (info == null) {
    128             Log.w(TAG, "Failed to find package info: " + Settings.EXTRA_APP_PACKAGE + " was " + pkg
    129                     + ", " + Settings.EXTRA_APP_UID + " was " + uid);
    130             toastAndFinish();
    131             return;
    132         }
    133 
    134         addPreferencesFromResource(R.xml.app_notification_settings);
    135         mBlock = (SwitchPreference) findPreference(KEY_BLOCK);
    136         mPriority = (SwitchPreference) findPreference(KEY_PRIORITY);
    137         mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
    138 
    139         final boolean secure = new LockPatternUtils(getActivity()).isSecure();
    140         final boolean enabled = getLockscreenNotificationsEnabled();
    141         final boolean allowPrivate = getLockscreenAllowPrivateNotifications();
    142         if (!secure || !enabled || !allowPrivate) {
    143             getPreferenceScreen().removePreference(mSensitive);
    144         }
    145 
    146         mAppRow = NotificationAppList.loadAppRow(pm, info.applicationInfo, mBackend);
    147         if (intent.hasExtra(EXTRA_HAS_SETTINGS_INTENT)) {
    148             // use settings intent from extra
    149             if (intent.getBooleanExtra(EXTRA_HAS_SETTINGS_INTENT, false)) {
    150                 mAppRow.settingsIntent = intent.getParcelableExtra(EXTRA_SETTINGS_INTENT);
    151             }
    152         } else {
    153             // load settings intent
    154             ArrayMap<String, AppRow> rows = new ArrayMap<String, AppRow>();
    155             rows.put(mAppRow.pkg, mAppRow);
    156             NotificationAppList.collectConfigActivities(getPackageManager(), rows);
    157         }
    158 
    159         mBlock.setChecked(mAppRow.banned);
    160         mPriority.setChecked(mAppRow.priority);
    161         if (mSensitive != null) {
    162             mSensitive.setChecked(mAppRow.sensitive);
    163         }
    164 
    165         mBlock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    166             @Override
    167             public boolean onPreferenceChange(Preference preference, Object newValue) {
    168                 final boolean block = (Boolean) newValue;
    169                 return mBackend.setNotificationsBanned(pkg, uid, block);
    170             }
    171         });
    172 
    173         mPriority.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    174             @Override
    175             public boolean onPreferenceChange(Preference preference, Object newValue) {
    176                 final boolean priority = (Boolean) newValue;
    177                 return mBackend.setHighPriority(pkg, uid, priority);
    178             }
    179         });
    180 
    181         if (mSensitive != null) {
    182             mSensitive.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    183                 @Override
    184                 public boolean onPreferenceChange(Preference preference, Object newValue) {
    185                     final boolean sensitive = (Boolean) newValue;
    186                     return mBackend.setSensitive(pkg, uid, sensitive);
    187                 }
    188             });
    189         }
    190 
    191         // Users cannot block notifications from system/signature packages
    192         if (Utils.isSystemPackage(pm, info)) {
    193             getPreferenceScreen().removePreference(mBlock);
    194             mPriority.setDependency(null); // don't have it depend on a preference that's gone
    195         }
    196     }
    197 
    198     private boolean getLockscreenNotificationsEnabled() {
    199         return Settings.Secure.getInt(getContentResolver(),
    200                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
    201     }
    202 
    203     private boolean getLockscreenAllowPrivateNotifications() {
    204         return Settings.Secure.getInt(getContentResolver(),
    205                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
    206     }
    207 
    208     private void toastAndFinish() {
    209         Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
    210         getActivity().finish();
    211     }
    212 
    213     private static PackageInfo findPackageInfo(PackageManager pm, String pkg, int uid) {
    214         final String[] packages = pm.getPackagesForUid(uid);
    215         if (packages != null && pkg != null) {
    216             final int N = packages.length;
    217             for (int i = 0; i < N; i++) {
    218                 final String p = packages[i];
    219                 if (pkg.equals(p)) {
    220                     try {
    221                         return pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
    222                     } catch (NameNotFoundException e) {
    223                         Log.w(TAG, "Failed to load package " + pkg, e);
    224                     }
    225                 }
    226             }
    227         }
    228         return null;
    229     }
    230 }
    231