blob: a3578469622dba9829829b619bdaa7d3a1126aa8 [file] [log] [blame]
Daniel Sandler328e2d22013-01-17 13:14:02 -05001/*
2 * Copyright (C) 2012 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
John Spurlock4a350512014-04-08 14:08:21 -040017package com.android.settings.notification;
Daniel Sandler328e2d22013-01-17 13:14:02 -050018
Fan Zhang92831fc2017-03-08 09:24:45 -080019import android.app.Activity;
20import android.app.ActivityManager;
Daniel Sandler328e2d22013-01-17 13:14:02 -050021import android.app.INotificationManager;
Fan Zhang92831fc2017-03-08 09:24:45 -080022import android.app.Notification;
23import android.app.PendingIntent;
John Spurlock4a350512014-04-08 14:08:21 -040024import android.content.ComponentName;
Daniel Sandler328e2d22013-01-17 13:14:02 -050025import android.content.Context;
Dan Sandler7a038eb2016-02-14 22:17:03 -050026import android.content.IntentSender;
Daniel Sandler95860492013-03-18 23:27:12 -040027import android.content.pm.ApplicationInfo;
Daniel Sandler328e2d22013-01-17 13:14:02 -050028import android.content.pm.PackageManager;
29import android.content.res.Resources;
Dan Sandler7a038eb2016-02-14 22:17:03 -050030import android.graphics.Typeface;
Daniel Sandler328e2d22013-01-17 13:14:02 -050031import android.graphics.drawable.Drawable;
Fan Zhang92831fc2017-03-08 09:24:45 -080032import android.os.Bundle;
33import android.os.Handler;
34import android.os.Parcel;
35import android.os.RemoteException;
36import android.os.ServiceManager;
37import android.os.UserHandle;
Chris Wren50018342014-05-14 15:29:11 -040038import android.service.notification.NotificationListenerService;
Dan Sandler7a038eb2016-02-14 22:17:03 -050039import android.service.notification.NotificationListenerService.Ranking;
40import android.service.notification.NotificationListenerService.RankingMap;
John Spurlock4a350512014-04-08 14:08:21 -040041import android.service.notification.StatusBarNotification;
Jason Monk39b46742015-09-10 15:52:51 -040042import android.support.v7.preference.Preference;
43import android.support.v7.preference.PreferenceViewHolder;
44import android.support.v7.widget.RecyclerView;
Dan Sandler7a038eb2016-02-14 22:17:03 -050045import android.text.SpannableString;
46import android.text.SpannableStringBuilder;
47import android.text.TextUtils;
48import android.text.style.StyleSpan;
Daniel Sandler328e2d22013-01-17 13:14:02 -050049import android.util.Log;
Daniel Sandler328e2d22013-01-17 13:14:02 -050050import android.view.View;
Daniel Sandler328e2d22013-01-17 13:14:02 -050051import android.widget.DateTimeView;
52import android.widget.ImageView;
Daniel Sandler328e2d22013-01-17 13:14:02 -050053import android.widget.TextView;
Daniel Sandler328e2d22013-01-17 13:14:02 -050054
Tamas Berghammer265d3c22016-06-22 15:34:45 +010055import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
John Spurlock4a350512014-04-08 14:08:21 -040056import com.android.settings.R;
57import com.android.settings.SettingsPreferenceFragment;
Fabrice Di Meglio9c3f11f2014-07-23 13:31:26 -070058import com.android.settings.Utils;
John Spurlock4a350512014-04-08 14:08:21 -040059
Fan Zhang92831fc2017-03-08 09:24:45 -080060import java.util.ArrayList;
61import java.util.Collections;
62import java.util.Comparator;
63import java.util.Date;
64import java.util.List;
Daniel Sandler328e2d22013-01-17 13:14:02 -050065
66public class NotificationStation extends SettingsPreferenceFragment {
67 private static final String TAG = NotificationStation.class.getSimpleName();
Daniel Sandler328e2d22013-01-17 13:14:02 -050068
Julia Reynolds1f178a92017-01-19 09:49:23 -050069 private static final boolean DEBUG = true;
Dan Sandler7a038eb2016-02-14 22:17:03 -050070 private static final boolean DUMP_EXTRAS = true;
71 private static final boolean DUMP_PARCEL = true;
Chris Wren6b11a062016-04-08 17:28:01 -040072 private Handler mHandler;
Fabrice Di Meglio6e106932014-07-23 13:07:52 -070073
74 private static class HistoricalNotificationInfo {
75 public String pkg;
76 public Drawable pkgicon;
77 public CharSequence pkgname;
78 public Drawable icon;
79 public CharSequence title;
80 public int priority;
81 public int user;
82 public long timestamp;
83 public boolean active;
Dan Sandler7a038eb2016-02-14 22:17:03 -050084 public CharSequence extra;
Fabrice Di Meglio6e106932014-07-23 13:07:52 -070085 }
86
Daniel Sandler95860492013-03-18 23:27:12 -040087 private PackageManager mPm;
Daniel Sandler328e2d22013-01-17 13:14:02 -050088 private INotificationManager mNoMan;
Dan Sandler7a038eb2016-02-14 22:17:03 -050089 private RankingMap mRanking;
Daniel Sandler738b8712013-03-18 23:06:15 -040090
91 private Runnable mRefreshListRunnable = new Runnable() {
92 @Override
93 public void run() {
94 refreshList();
95 }
96 };
97
Dan Sandler8b797c22016-02-29 22:29:10 -050098 private final NotificationListenerService mListener = new NotificationListenerService() {
Daniel Sandler8fd91ae2013-02-14 17:05:52 -050099 @Override
Dan Sandler7a038eb2016-02-14 22:17:03 -0500100 public void onNotificationPosted(StatusBarNotification sbn, RankingMap ranking) {
Chris Wren6b11a062016-04-08 17:28:01 -0400101 logd("onNotificationPosted: %s, with update for %d", sbn.getNotification(),
102 ranking == null ? 0 : ranking.getOrderedKeys().length);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500103 mRanking = ranking;
Chris Wren6b11a062016-04-08 17:28:01 -0400104 scheduleRefreshList();
Daniel Sandler8fd91ae2013-02-14 17:05:52 -0500105 }
106
107 @Override
Dan Sandler7a038eb2016-02-14 22:17:03 -0500108 public void onNotificationRemoved(StatusBarNotification notification, RankingMap ranking) {
Chris Wren6b11a062016-04-08 17:28:01 -0400109 logd("onNotificationRankingUpdate with update for %d",
110 ranking == null ? 0 : ranking.getOrderedKeys().length);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500111 mRanking = ranking;
Chris Wren6b11a062016-04-08 17:28:01 -0400112 scheduleRefreshList();
Daniel Sandler8fd91ae2013-02-14 17:05:52 -0500113 }
Dan Sandler7a038eb2016-02-14 22:17:03 -0500114
115 @Override
116 public void onNotificationRankingUpdate(RankingMap ranking) {
Chris Wren6b11a062016-04-08 17:28:01 -0400117 logd("onNotificationRankingUpdate with update for %d",
118 ranking == null ? 0 : ranking.getOrderedKeys().length);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500119 mRanking = ranking;
Chris Wren6b11a062016-04-08 17:28:01 -0400120 scheduleRefreshList();
Dan Sandler7a038eb2016-02-14 22:17:03 -0500121 }
Julia Reynolds518b93f2016-02-25 09:35:44 -0500122
123 @Override
124 public void onListenerConnected() {
125 mRanking = getCurrentRanking();
Chris Wren6b11a062016-04-08 17:28:01 -0400126 logd("onListenerConnected with update for %d",
127 mRanking == null ? 0 : mRanking.getOrderedKeys().length);
128 scheduleRefreshList();
Julia Reynolds518b93f2016-02-25 09:35:44 -0500129 }
Daniel Sandler8fd91ae2013-02-14 17:05:52 -0500130 };
Daniel Sandler328e2d22013-01-17 13:14:02 -0500131
Chris Wren6b11a062016-04-08 17:28:01 -0400132 private void scheduleRefreshList() {
133 if (mHandler != null) {
134 mHandler.removeCallbacks(mRefreshListRunnable);
135 mHandler.postDelayed(mRefreshListRunnable, 100);
136 }
137 }
138
Daniel Sandler328e2d22013-01-17 13:14:02 -0500139 private Context mContext;
140
Daniel Sandler738b8712013-03-18 23:06:15 -0400141 private final Comparator<HistoricalNotificationInfo> mNotificationSorter
142 = new Comparator<HistoricalNotificationInfo>() {
143 @Override
144 public int compare(HistoricalNotificationInfo lhs,
145 HistoricalNotificationInfo rhs) {
Ian Rogers03936ce2016-06-07 00:02:42 -0700146 return Long.compare(rhs.timestamp, lhs.timestamp);
Daniel Sandler738b8712013-03-18 23:06:15 -0400147 }
148 };
149
Daniel Sandler328e2d22013-01-17 13:14:02 -0500150 @Override
151 public void onAttach(Activity activity) {
152 logd("onAttach(%s)", activity.getClass().getSimpleName());
153 super.onAttach(activity);
Chris Wren6b11a062016-04-08 17:28:01 -0400154 mHandler = new Handler(activity.getMainLooper());
Daniel Sandler328e2d22013-01-17 13:14:02 -0500155 mContext = activity;
Daniel Sandler95860492013-03-18 23:27:12 -0400156 mPm = mContext.getPackageManager();
Daniel Sandler328e2d22013-01-17 13:14:02 -0500157 mNoMan = INotificationManager.Stub.asInterface(
158 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
159 }
160
161 @Override
Chris Wren6b11a062016-04-08 17:28:01 -0400162 public void onDetach() {
163 logd("onDetach()");
164 mHandler.removeCallbacks(mRefreshListRunnable);
165 mHandler = null;
166 super.onDetach();
167 }
168
169 @Override
Dan Sandler8b797c22016-02-29 22:29:10 -0500170 public void onPause() {
Chris Wren50018342014-05-14 15:29:11 -0400171 try {
172 mListener.unregisterAsSystemService();
173 } catch (RemoteException e) {
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700174 Log.e(TAG, "Cannot unregister listener", e);
Chris Wren50018342014-05-14 15:29:11 -0400175 }
Dan Sandler8b797c22016-02-29 22:29:10 -0500176 super.onPause();
Chris Wren50018342014-05-14 15:29:11 -0400177 }
178
179 @Override
Fan Zhang65076132016-08-08 10:25:13 -0700180 public int getMetricsCategory() {
Chris Wren9d1bfd12016-01-26 18:04:01 -0500181 return MetricsEvent.NOTIFICATION_STATION;
Chris Wren8a963ba2015-03-20 10:29:14 -0400182 }
183
184 @Override
Daniel Sandler328e2d22013-01-17 13:14:02 -0500185 public void onActivityCreated(Bundle savedInstanceState) {
186 logd("onActivityCreated(%s)", savedInstanceState);
187 super.onActivityCreated(savedInstanceState);
188
Jason Monk39b46742015-09-10 15:52:51 -0400189 RecyclerView listView = getListView();
Fabrice Di Meglio0f4a7792014-07-28 18:25:14 -0700190 Utils.forceCustomPadding(listView, false /* non additive padding */);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500191 }
192
193 @Override
Daniel Sandler328e2d22013-01-17 13:14:02 -0500194 public void onResume() {
195 logd("onResume()");
196 super.onResume();
Dan Sandler8b797c22016-02-29 22:29:10 -0500197 try {
198 mListener.registerAsSystemService(mContext, new ComponentName(mContext.getPackageName(),
199 this.getClass().getCanonicalName()), ActivityManager.getCurrentUser());
200 } catch (RemoteException e) {
201 Log.e(TAG, "Cannot register listener", e);
202 }
Daniel Sandler8fd91ae2013-02-14 17:05:52 -0500203 refreshList();
Daniel Sandler328e2d22013-01-17 13:14:02 -0500204 }
205
Daniel Sandler8fd91ae2013-02-14 17:05:52 -0500206 private void refreshList() {
Daniel Sandler328e2d22013-01-17 13:14:02 -0500207 List<HistoricalNotificationInfo> infos = loadNotifications();
208 if (infos != null) {
Jason Monk39b46742015-09-10 15:52:51 -0400209 final int N = infos.size();
210 logd("adding %d infos", N);
211 Collections.sort(infos, mNotificationSorter);
212 if (getPreferenceScreen() == null) {
213 setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
214 }
215 getPreferenceScreen().removeAll();
216 for (int i = 0; i < N; i++) {
217 getPreferenceScreen().addPreference(
218 new HistoricalNotificationPreference(getPrefContext(), infos.get(i)));
219 }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500220 }
221 }
222
223 private static void logd(String msg, Object... args) {
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700224 if (DEBUG) {
Daniel Sandler328e2d22013-01-17 13:14:02 -0500225 Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700226 }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500227 }
228
Dan Sandler7a038eb2016-02-14 22:17:03 -0500229 private static CharSequence bold(CharSequence cs) {
230 if (cs.length() == 0) return cs;
231 SpannableString ss = new SpannableString(cs);
232 ss.setSpan(new StyleSpan(Typeface.BOLD), 0, cs.length(), 0);
233 return ss;
234 }
235
236 private static String getTitleString(Notification n) {
Dan Sandler8b797c22016-02-29 22:29:10 -0500237 CharSequence title = null;
Dan Sandler7a038eb2016-02-14 22:17:03 -0500238 if (n.extras != null) {
Dan Sandler8b797c22016-02-29 22:29:10 -0500239 title = n.extras.getCharSequence(Notification.EXTRA_TITLE);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500240 if (TextUtils.isEmpty(title)) {
Dan Sandler8b797c22016-02-29 22:29:10 -0500241 title = n.extras.getCharSequence(Notification.EXTRA_TEXT);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500242 }
243 }
244 if (TextUtils.isEmpty(title) && !TextUtils.isEmpty(n.tickerText)) {
Dan Sandler8b797c22016-02-29 22:29:10 -0500245 title = n.tickerText;
Dan Sandler7a038eb2016-02-14 22:17:03 -0500246 }
Dan Sandler8b797c22016-02-29 22:29:10 -0500247 return String.valueOf(title);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500248 }
249
250 private static String formatPendingIntent(PendingIntent pi) {
251 final StringBuilder sb = new StringBuilder();
252 final IntentSender is = pi.getIntentSender();
253 sb.append("Intent(pkg=").append(is.getCreatorPackage());
254 try {
255 final boolean isActivity =
Sudheer Shankaacb1a612016-11-10 15:30:14 -0800256 ActivityManager.getService().isIntentSenderAnActivity(is.getTarget());
Dan Sandler7a038eb2016-02-14 22:17:03 -0500257 if (isActivity) sb.append(" (activity)");
258 } catch (RemoteException ex) {}
259 sb.append(")");
260 return sb.toString();
261 }
262
Daniel Sandler328e2d22013-01-17 13:14:02 -0500263 private List<HistoricalNotificationInfo> loadNotifications() {
264 final int currentUserId = ActivityManager.getCurrentUser();
265 try {
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700266 StatusBarNotification[] active = mNoMan.getActiveNotifications(
267 mContext.getPackageName());
268 StatusBarNotification[] dismissed = mNoMan.getHistoricalNotifications(
269 mContext.getPackageName(), 50);
Daniel Sandlerc97593b2013-03-07 15:43:30 -0500270
Daniel Sandler328e2d22013-01-17 13:14:02 -0500271 List<HistoricalNotificationInfo> list
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500272 = new ArrayList<HistoricalNotificationInfo>(active.length + dismissed.length);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500273
Dan Sandler7a038eb2016-02-14 22:17:03 -0500274 final Ranking rank = new Ranking();
275
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500276 for (StatusBarNotification[] resultset
277 : new StatusBarNotification[][] { active, dismissed }) {
278 for (StatusBarNotification sbn : resultset) {
Dan Sandler7a038eb2016-02-14 22:17:03 -0500279 if (sbn.getUserId() != UserHandle.USER_ALL & sbn.getUserId() != currentUserId) {
280 continue;
281 }
282
283 final Notification n = sbn.getNotification();
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500284 final HistoricalNotificationInfo info = new HistoricalNotificationInfo();
Daniel Sandlerfbfddb02013-04-25 17:01:01 -0400285 info.pkg = sbn.getPackageName();
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500286 info.user = sbn.getUserId();
Dan Sandler7a038eb2016-02-14 22:17:03 -0500287 info.icon = loadIconDrawable(info.pkg, info.user, n.icon);
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500288 info.pkgicon = loadPackageIconDrawable(info.pkg, info.user);
Daniel Sandler95860492013-03-18 23:27:12 -0400289 info.pkgname = loadPackageName(info.pkg);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500290 info.title = getTitleString(n);
291 if (TextUtils.isEmpty(info.title)) {
292 info.title = getString(R.string.notification_log_no_title);
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500293 }
Daniel Sandlerfbfddb02013-04-25 17:01:01 -0400294 info.timestamp = sbn.getPostTime();
Dan Sandler7a038eb2016-02-14 22:17:03 -0500295 info.priority = n.priority;
Daniel Sandler328e2d22013-01-17 13:14:02 -0500296
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500297 info.active = (resultset == active);
298
Dan Sandler7a038eb2016-02-14 22:17:03 -0500299 final SpannableStringBuilder sb = new SpannableStringBuilder();
300 final String delim = getString(R.string.notification_log_details_delimiter);
301 sb.append(bold(getString(R.string.notification_log_details_package)))
302 .append(delim)
303 .append(info.pkg)
304 .append("\n")
305 .append(bold(getString(R.string.notification_log_details_key)))
306 .append(delim)
307 .append(sbn.getKey());
308 sb.append("\n")
309 .append(bold(getString(R.string.notification_log_details_icon)))
310 .append(delim)
311 .append(n.getSmallIcon().toString());
Chris Wren6b11a062016-04-08 17:28:01 -0400312 if (sbn.isGroup()) {
Dan Sandler7a038eb2016-02-14 22:17:03 -0500313 sb.append("\n")
314 .append(bold(getString(R.string.notification_log_details_group)))
315 .append(delim)
Chris Wren6b11a062016-04-08 17:28:01 -0400316 .append(sbn.getGroupKey());
Dan Sandler7a038eb2016-02-14 22:17:03 -0500317 if (n.isGroupSummary()) {
318 sb.append(bold(
319 getString(R.string.notification_log_details_group_summary)));
320 }
Daniel Sandlerc00e4102013-03-07 16:39:06 -0500321 }
Dan Sandler7a038eb2016-02-14 22:17:03 -0500322 sb.append("\n")
323 .append(bold(getString(R.string.notification_log_details_sound)))
324 .append(delim);
325 if (0 != (n.defaults & Notification.DEFAULT_SOUND)) {
326 sb.append(getString(R.string.notification_log_details_default));
327 } else if (n.sound != null) {
328 sb.append(n.sound.toString());
329 } else {
330 sb.append(getString(R.string.notification_log_details_none));
331 }
332 sb.append("\n")
333 .append(bold(getString(R.string.notification_log_details_vibrate)))
334 .append(delim);
335 if (0 != (n.defaults & Notification.DEFAULT_VIBRATE)) {
336 sb.append(getString(R.string.notification_log_details_default));
337 } else if (n.vibrate != null) {
338 for (int vi=0;vi<n.vibrate.length;vi++) {
339 if (vi > 0) sb.append(',');
340 sb.append(String.valueOf(n.vibrate[vi]));
341 }
342 } else {
343 sb.append(getString(R.string.notification_log_details_none));
344 }
345 sb.append("\n")
346 .append(bold(getString(R.string.notification_log_details_visibility)))
347 .append(delim)
348 .append(Notification.visibilityToString(n.visibility));
349 if (n.publicVersion != null) {
350 sb.append("\n")
351 .append(bold(getString(
352 R.string.notification_log_details_public_version)))
353 .append(delim)
354 .append(getTitleString(n.publicVersion));
355 }
356 sb.append("\n")
357 .append(bold(getString(R.string.notification_log_details_priority)))
358 .append(delim)
359 .append(Notification.priorityToString(n.priority));
Chris Wren6b11a062016-04-08 17:28:01 -0400360 if (resultset == active) {
361 // mRanking only applies to active notifications
362 if (mRanking != null && mRanking.getRanking(sbn.getKey(), rank)) {
Dan Sandler7a038eb2016-02-14 22:17:03 -0500363 sb.append("\n")
364 .append(bold(getString(
Chris Wren6b11a062016-04-08 17:28:01 -0400365 R.string.notification_log_details_importance)))
Dan Sandler7a038eb2016-02-14 22:17:03 -0500366 .append(delim)
Chris Wren6b11a062016-04-08 17:28:01 -0400367 .append(Ranking.importanceToString(rank.getImportance()));
368 if (rank.getImportanceExplanation() != null) {
369 sb.append("\n")
370 .append(bold(getString(
371 R.string.notification_log_details_explanation)))
372 .append(delim)
373 .append(rank.getImportanceExplanation());
374 }
Julia Reynolds1f178a92017-01-19 09:49:23 -0500375 sb.append("\n")
376 .append(bold(getString(
377 R.string.notification_log_details_badge)))
378 .append(delim)
379 .append(Boolean.toString(rank.canShowBadge()));
Chris Wren6b11a062016-04-08 17:28:01 -0400380 } else {
381 if (mRanking == null) {
382 sb.append("\n")
383 .append(bold(getString(
384 R.string.notification_log_details_ranking_null)));
385 } else {
386 sb.append("\n")
387 .append(bold(getString(
388 R.string.notification_log_details_ranking_none)));
389 }
Dan Sandler7a038eb2016-02-14 22:17:03 -0500390 }
391 }
392 if (n.contentIntent != null) {
393 sb.append("\n")
394 .append(bold(getString(
395 R.string.notification_log_details_content_intent)))
396 .append(delim)
397 .append(formatPendingIntent(n.contentIntent));
398 }
399 if (n.deleteIntent != null) {
400 sb.append("\n")
401 .append(bold(getString(
402 R.string.notification_log_details_delete_intent)))
403 .append(delim)
404 .append(formatPendingIntent(n.deleteIntent));
405 }
406 if (n.fullScreenIntent != null) {
407 sb.append("\n")
408 .append(bold(getString(
409 R.string.notification_log_details_full_screen_intent)))
410 .append(delim)
411 .append(formatPendingIntent(n.fullScreenIntent));
412 }
413 if (n.actions != null && n.actions.length > 0) {
414 sb.append("\n")
415 .append(bold(getString(R.string.notification_log_details_actions)));
416 for (int ai=0; ai<n.actions.length; ai++) {
417 final Notification.Action action = n.actions[ai];
418 sb.append("\n ").append(String.valueOf(ai)).append(' ')
419 .append(bold(getString(
420 R.string.notification_log_details_title)))
421 .append(delim)
Julia Reynolds9bcc04c2016-06-20 10:23:44 -0400422 .append(action.title);
423 if (action.actionIntent != null) {
424 sb.append("\n ")
425 .append(bold(getString(
426 R.string.notification_log_details_content_intent)))
427 .append(delim)
428 .append(formatPendingIntent(action.actionIntent));
429 }
Dan Sandler7a038eb2016-02-14 22:17:03 -0500430 if (action.getRemoteInputs() != null) {
Julia Reynolds9bcc04c2016-06-20 10:23:44 -0400431 sb.append("\n ")
Dan Sandler7a038eb2016-02-14 22:17:03 -0500432 .append(bold(getString(
433 R.string.notification_log_details_remoteinput)))
434 .append(delim)
435 .append(String.valueOf(action.getRemoteInputs().length));
436 }
437 }
438 }
439 if (n.contentView != null) {
440 sb.append("\n")
441 .append(bold(getString(
442 R.string.notification_log_details_content_view)))
443 .append(delim)
444 .append(n.contentView.toString());
445 }
446
447 if (DUMP_EXTRAS) {
448 if (n.extras != null && n.extras.size() > 0) {
449 sb.append("\n")
450 .append(bold(getString(
451 R.string.notification_log_details_extras)));
452 for (String extraKey : n.extras.keySet()) {
453 String val = String.valueOf(n.extras.get(extraKey));
454 if (val.length() > 100) val = val.substring(0, 100) + "...";
455 sb.append("\n ").append(extraKey).append(delim).append(val);
456 }
457 }
458 }
459 if (DUMP_PARCEL) {
460 final Parcel p = Parcel.obtain();
461 n.writeToParcel(p, 0);
462 sb.append("\n")
463 .append(bold(getString(R.string.notification_log_details_parcel)))
464 .append(delim)
465 .append(String.valueOf(p.dataPosition()))
466 .append(' ')
467 .append(bold(getString(R.string.notification_log_details_ashmem)))
468 .append(delim)
469 .append(String.valueOf(p.getBlobAshmemSize()))
470 .append("\n");
471 }
472
473 info.extra = sb;
474
475 logd(" [%d] %s: %s", info.timestamp, info.pkg, info.title);
476 list.add(info);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500477 }
478 }
479
480 return list;
481 } catch (RemoteException e) {
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700482 Log.e(TAG, "Cannot load Notifications: ", e);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500483 }
484 return null;
485 }
486
487 private Resources getResourcesForUserPackage(String pkg, int userId) {
488 Resources r = null;
489
490 if (pkg != null) {
491 try {
492 if (userId == UserHandle.USER_ALL) {
Xiaohui Chen6f038292015-09-02 16:54:00 -0700493 userId = UserHandle.USER_SYSTEM;
Daniel Sandler328e2d22013-01-17 13:14:02 -0500494 }
Daniel Sandler95860492013-03-18 23:27:12 -0400495 r = mPm.getResourcesForApplicationAsUser(pkg, userId);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500496 } catch (PackageManager.NameNotFoundException ex) {
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700497 Log.e(TAG, "Icon package not found: " + pkg, ex);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500498 return null;
499 }
500 } else {
501 r = mContext.getResources();
502 }
503 return r;
504 }
505
506 private Drawable loadPackageIconDrawable(String pkg, int userId) {
507 Drawable icon = null;
508 try {
Daniel Sandler95860492013-03-18 23:27:12 -0400509 icon = mPm.getApplicationIcon(pkg);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500510 } catch (PackageManager.NameNotFoundException e) {
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700511 Log.e(TAG, "Cannot get application icon", e);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500512 }
513
514 return icon;
515 }
516
Daniel Sandler95860492013-03-18 23:27:12 -0400517 private CharSequence loadPackageName(String pkg) {
518 try {
519 ApplicationInfo info = mPm.getApplicationInfo(pkg,
Amith Yamasani21556cd2016-11-01 15:49:21 -0700520 PackageManager.MATCH_ANY_USER);
Daniel Sandler95860492013-03-18 23:27:12 -0400521 if (info != null) return mPm.getApplicationLabel(info);
522 } catch (PackageManager.NameNotFoundException e) {
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700523 Log.e(TAG, "Cannot load package name", e);
Daniel Sandler95860492013-03-18 23:27:12 -0400524 }
525 return pkg;
526 }
527
Daniel Sandler328e2d22013-01-17 13:14:02 -0500528 private Drawable loadIconDrawable(String pkg, int userId, int resId) {
529 Resources r = getResourcesForUserPackage(pkg, userId);
530
531 if (resId == 0) {
532 return null;
533 }
534
535 try {
Alan Viverette0ba89bd2014-10-10 10:58:58 -0700536 return r.getDrawable(resId, null);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500537 } catch (RuntimeException e) {
538 Log.w(TAG, "Icon not found in "
539 + (pkg != null ? resId : "<system>")
Fabrice Di Meglio6e106932014-07-23 13:07:52 -0700540 + ": " + Integer.toHexString(resId), e);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500541 }
542
543 return null;
544 }
545
Fan Zhang92831fc2017-03-08 09:24:45 -0800546 private static class HistoricalNotificationPreference extends Preference {
Jason Monk39b46742015-09-10 15:52:51 -0400547 private final HistoricalNotificationInfo mInfo;
Daniel Sandler328e2d22013-01-17 13:14:02 -0500548
Jason Monk39b46742015-09-10 15:52:51 -0400549 public HistoricalNotificationPreference(Context context, HistoricalNotificationInfo info) {
550 super(context);
551 setLayoutResource(R.layout.notification_log_row);
552 mInfo = info;
Daniel Sandler328e2d22013-01-17 13:14:02 -0500553 }
554
555 @Override
Jason Monk39b46742015-09-10 15:52:51 -0400556 public void onBindViewHolder(PreferenceViewHolder row) {
Dan Sandler7a038eb2016-02-14 22:17:03 -0500557 super.onBindViewHolder(row);
558
Jason Monk39b46742015-09-10 15:52:51 -0400559 if (mInfo.icon != null) {
Dan Sandler7a038eb2016-02-14 22:17:03 -0500560 ((ImageView) row.findViewById(R.id.icon)).setImageDrawable(mInfo.icon);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500561 }
Jason Monk39b46742015-09-10 15:52:51 -0400562 if (mInfo.pkgicon != null) {
563 ((ImageView) row.findViewById(R.id.pkgicon)).setImageDrawable(mInfo.pkgicon);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500564 }
565
Jason Monk39b46742015-09-10 15:52:51 -0400566 ((DateTimeView) row.findViewById(R.id.timestamp)).setTime(mInfo.timestamp);
Dan Sandler7a038eb2016-02-14 22:17:03 -0500567 ((TextView) row.findViewById(R.id.title)).setText(mInfo.title);
Jason Monk39b46742015-09-10 15:52:51 -0400568 ((TextView) row.findViewById(R.id.pkgname)).setText(mInfo.pkgname);
Daniel Sandler95860492013-03-18 23:27:12 -0400569
Dan Sandler7a038eb2016-02-14 22:17:03 -0500570 final TextView extra = (TextView) row.findViewById(R.id.extra);
571 extra.setText(mInfo.extra);
572 extra.setVisibility(View.GONE);
573
574 row.itemView.setOnClickListener(
575 new View.OnClickListener() {
576 @Override
577 public void onClick(View view) {
578 extra.setVisibility(extra.getVisibility() == View.VISIBLE
579 ? View.GONE : View.VISIBLE);
580 }
581 });
582
Jason Monk39b46742015-09-10 15:52:51 -0400583 row.itemView.setAlpha(mInfo.active ? 1.0f : 0.5f);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500584 }
585
Jason Monk39b46742015-09-10 15:52:51 -0400586 @Override
587 public void performClick() {
Dan Sandler7a038eb2016-02-14 22:17:03 -0500588// Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
589// Uri.fromParts("package", mInfo.pkg, null));
590// intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
591// getContext().startActivity(intent);
Daniel Sandler328e2d22013-01-17 13:14:02 -0500592 }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500593 }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500594}