• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.storagemanager.automatic;
18 
19 import android.app.Notification;
20 import android.app.NotificationManager;
21 import android.app.PendingIntent;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.SharedPreferences;
26 import android.content.res.Resources;
27 import android.provider.Settings;
28 
29 import com.android.storagemanager.R;
30 
31 import java.util.concurrent.TimeUnit;
32 
33 /**
34  * NotificationController handles the responses to the Automatic Storage Management low storage
35  * notification.
36  */
37 public class NotificationController extends BroadcastReceiver {
38     /**
39      * Intent action for if the user taps "Turn on" for the automatic storage manager.
40      */
41     public static final String INTENT_ACTION_ACTIVATE_ASM =
42             "com.android.storagemanager.automatic.ACTIVATE";
43 
44     /**
45      * Intent action for if the user swipes the notification away.
46      */
47     public static final String INTENT_ACTION_DISMISS =
48             "com.android.storagemanager.automatic.DISMISS";
49 
50     /**
51      * Intent action for if the user explicitly hits "No thanks" on the notification.
52      */
53     public static final String INTENT_ACTION_NO_THANKS =
54             "com.android.storagemanager.automatic.NO_THANKS";
55 
56 
57     /**
58      * Intent action for if the user explicitly hits "No thanks" on the notification.
59      */
60     private static final String INTENT_ACTION_DEBUG_NOTIFICATION =
61             "com.android.storagemanager.automatic.DEBUG_SHOW_NOTIFICATION";
62 
63     /**
64      * Intent extra for the notification id.
65      */
66     public static final String INTENT_EXTRA_ID = "id";
67 
68     private static final String SHARED_PREFERENCES_NAME = "NotificationController";
69     private static final String NOTIFICATION_NEXT_SHOW_TIME = "notification_next_show_time";
70     private static final String NOTIFICATION_SHOWN_COUNT = "notification_shown_count";
71 
72     private static final long DISMISS_DELAY = TimeUnit.DAYS.toMillis(15);
73     private static final long NO_THANKS_DELAY = TimeUnit.DAYS.toMillis(90);
74     private static final long MAXIMUM_SHOWN_COUNT = 4;
75     private static final int NOTIFICATION_ID = 0;
76 
77     @Override
onReceive(Context context, Intent intent)78     public void onReceive(Context context, Intent intent) {
79         switch (intent.getAction()) {
80             case INTENT_ACTION_ACTIVATE_ASM:
81                 Settings.Secure.putInt(context.getContentResolver(),
82                         Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
83                         1);
84                 break;
85             case INTENT_ACTION_NO_THANKS:
86                 delayNextNotification(context, NO_THANKS_DELAY);
87                 break;
88             case INTENT_ACTION_DISMISS:
89                 delayNextNotification(context, DISMISS_DELAY);
90                 break;
91             case INTENT_ACTION_DEBUG_NOTIFICATION:
92                 showNotification(context);
93                 return;
94         }
95         cancelNotification(context, intent);
96     }
97 
98     /**
99      * If the conditions for showing the activation notification are met, show the activation
100      * notification.
101      * @param context Context to use for getting resources and to display the notification.
102      */
maybeShowNotification(Context context)103     public static void maybeShowNotification(Context context) {
104         if (shouldShowNotification(context)) {
105             showNotification(context);
106         }
107     }
108 
shouldShowNotification(Context context)109     private static boolean shouldShowNotification(Context context) {
110         SharedPreferences sp = context.getSharedPreferences(
111                 SHARED_PREFERENCES_NAME,
112                 Context.MODE_PRIVATE);
113         int timesShown = sp.getInt(NOTIFICATION_SHOWN_COUNT, 0);
114         if (timesShown > MAXIMUM_SHOWN_COUNT) {
115             return false;
116         }
117 
118         long nextTimeToShow = sp.getLong(NOTIFICATION_NEXT_SHOW_TIME, 0);
119 
120         return System.currentTimeMillis() > nextTimeToShow;
121     }
122 
showNotification(Context context)123     private static void showNotification(Context context) {
124         Resources res = context.getResources();
125         Intent noThanksIntent = new Intent(INTENT_ACTION_NO_THANKS);
126         noThanksIntent.putExtra(INTENT_EXTRA_ID, NOTIFICATION_ID);
127         Notification.Action.Builder cancelAction = new Notification.Action.Builder(null,
128                 res.getString(R.string.automatic_storage_manager_cancel_button),
129                 PendingIntent.getBroadcast(context, 0, noThanksIntent,
130                         PendingIntent.FLAG_UPDATE_CURRENT));
131 
132 
133         Intent activateIntent = new Intent(INTENT_ACTION_ACTIVATE_ASM);
134         activateIntent.putExtra(INTENT_EXTRA_ID, NOTIFICATION_ID);
135         Notification.Action.Builder activateAutomaticAction = new Notification.Action.Builder(null,
136                 res.getString(R.string.automatic_storage_manager_activate_button),
137                 PendingIntent.getBroadcast(context, 0, activateIntent,
138                         PendingIntent.FLAG_UPDATE_CURRENT));
139 
140         Intent dismissIntent = new Intent(INTENT_ACTION_DISMISS);
141         dismissIntent.putExtra(INTENT_EXTRA_ID, NOTIFICATION_ID);
142         PendingIntent deleteIntent = PendingIntent.getBroadcast(context, 0,
143                 new Intent(INTENT_ACTION_DISMISS),
144                 PendingIntent.FLAG_ONE_SHOT);
145 
146         Notification.Builder builder = new Notification.Builder(context)
147                 .setSmallIcon(R.drawable.ic_settings_24dp)
148                 .setContentTitle(
149                         res.getString(R.string.automatic_storage_manager_notification_title))
150                 .setContentText(
151                         res.getString(R.string.automatic_storage_manager_notification_summary))
152                 .setStyle(new Notification.BigTextStyle().bigText(
153                         res.getString(R.string.automatic_storage_manager_notification_summary)))
154                 .addAction(cancelAction.build())
155                 .addAction(activateAutomaticAction.build())
156                 .setDeleteIntent(deleteIntent);
157 
158         NotificationManager manager =
159                 ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE));
160         manager.notify(NOTIFICATION_ID, builder.build());
161     }
162 
cancelNotification(Context context, Intent intent)163     private void cancelNotification(Context context, Intent intent) {
164         int id = intent.getIntExtra(INTENT_EXTRA_ID, -1);
165         if (id == -1) {
166             return;
167         }
168         NotificationManager manager = (NotificationManager) context
169                 .getSystemService(Context.NOTIFICATION_SERVICE);
170         manager.cancel(id);
171 
172         incrementNotificationShownCount(context);
173     }
174 
incrementNotificationShownCount(Context context)175     private void incrementNotificationShownCount(Context context) {
176         SharedPreferences sp = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
177                 Context.MODE_PRIVATE);
178         SharedPreferences.Editor editor = sp.edit();
179         int shownCount = sp.getInt(NotificationController.NOTIFICATION_SHOWN_COUNT, 0) + 1;
180         editor.putInt(NotificationController.NOTIFICATION_SHOWN_COUNT, shownCount);
181         editor.apply();
182     }
183 
delayNextNotification(Context context, long timeInMillis)184     private void delayNextNotification(Context context, long timeInMillis) {
185         SharedPreferences sp = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
186                 Context.MODE_PRIVATE);
187         SharedPreferences.Editor editor = sp.edit();
188         editor.putLong(NOTIFICATION_NEXT_SHOW_TIME,
189                 System.currentTimeMillis() + timeInMillis);
190         editor.apply();
191     }
192 }
193