Merge "Notify user that scans are still active" into jb-mr2-dev
diff --git a/res/layout/notification_log_row.xml b/res/layout/notification_log_row.xml
index 26e72cb..284e9ea 100644
--- a/res/layout/notification_log_row.xml
+++ b/res/layout/notification_log_row.xml
@@ -13,84 +13,105 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/widget_frame"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_toStartOf="@+id/divider"
- android:background="?android:attr/selectableItemBackground" >
+ android:paddingBottom="6dp"
+ android:paddingTop="6dp"
+ android:orientation="vertical"
+ android:background="?android:attr/selectableItemBackground"
+ >
- <!-- Dream icon -->
-
- <ImageView
- android:id="@+id/pkgicon"
- android:layout_width="@*android:dimen/status_bar_icon_size"
+ <RelativeLayout
+ android:layout_width="match_parent"
android:layout_height="@*android:dimen/status_bar_icon_size"
- android:layout_centerVertical="true"
- android:layout_marginBottom="6dp"
- android:layout_marginStart="0dp"
- android:layout_marginEnd="6dp"
- android:layout_marginTop="6dp"
- android:contentDescription="@null"
- android:adjustViewBounds="true"
- android:maxHeight="@*android:dimen/status_bar_icon_size"
- android:maxWidth="@*android:dimen/status_bar_icon_size"
- android:scaleType="fitCenter" />
+ android:layout_marginBottom="4dp"
+ >
- <ImageView
- android:id="@android:id/icon"
- android:layout_width="@*android:dimen/status_bar_icon_size"
- android:layout_height="@*android:dimen/status_bar_icon_size"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@id/pkgicon"
- android:layout_marginBottom="6dp"
- android:layout_marginStart="0dp"
- android:layout_marginEnd="8dp"
- android:layout_marginTop="6dp"
- android:contentDescription="@null"
- android:adjustViewBounds="true"
- android:maxHeight="@*android:dimen/status_bar_icon_size"
- android:maxWidth="@*android:dimen/status_bar_icon_size"
- android:scaleType="fitCenter" />
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@*android:dimen/status_bar_icon_size"
+ android:layout_height="@*android:dimen/status_bar_icon_size"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/pkgicon"
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="8dp"
+ android:contentDescription="@null"
+ android:adjustViewBounds="true"
+ android:maxHeight="@*android:dimen/status_bar_icon_size"
+ android:maxWidth="@*android:dimen/status_bar_icon_size"
+ android:scaleType="fitCenter" />
- <!-- Dream caption -->
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toStartOf="@+id/timestamp"
+ android:layout_toEndOf="@android:id/icon"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:textAlignment="viewStart"
+ android:labelFor="@android:id/button2" />
+
+ <DateTimeView
+ android:id="@+id/timestamp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@android:id/widget_frame"
+ android:layout_alignParentEnd="true"
+ android:layout_alignTop="@android:id/widget_frame"
+ android:layout_centerVertical="true"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAlignment="viewEnd"
+ />
+ </RelativeLayout>
<TextView
- android:id="@android:id/title"
+ android:id="@+id/extra"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toStartOf="@+id/timestamp"
- android:layout_toEndOf="@android:id/icon"
+ android:orientation="horizontal"
+ android:layout_marginStart="30dp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textAlignment="viewStart"
- android:labelFor="@android:id/button2" />
-
- <!-- Dream radio button -->
-
- <!--<RadioButton
- android:id="@android:id/button1"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- android:duplicateParentState="true"
- android:clickable="false"
- android:focusable="false" />-->
-
- <DateTimeView
- android:id="@+id/timestamp"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignBottom="@android:id/widget_frame"
- android:layout_alignParentEnd="true"
- android:layout_alignTop="@android:id/widget_frame"
- android:layout_centerVertical="true"
- android:ellipsize="end"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textAlignment="viewEnd"
/>
-</RelativeLayout>
\ No newline at end of file
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="@*android:dimen/status_bar_icon_size"
+ android:orientation="horizontal"
+ android:layout_marginStart="30dp"
+ >
+
+ <ImageView
+ android:id="@+id/pkgicon"
+ android:layout_width="@*android:dimen/status_bar_icon_size"
+ android:layout_height="@*android:dimen/status_bar_icon_size"
+ android:layout_marginStart="0dp"
+ android:layout_marginEnd="6dp"
+ android:contentDescription="@null"
+ android:adjustViewBounds="true"
+ android:maxHeight="@*android:dimen/status_bar_icon_size"
+ android:maxWidth="@*android:dimen/status_bar_icon_size"
+ android:scaleType="fitCenter" />
+
+ <TextView
+ android:id="@+id/pkgname"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left|center_vertical"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAlignment="viewStart"
+ />
+
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/src/com/android/settings/NotificationStation.java b/src/com/android/settings/NotificationStation.java
index 1242d85..1badfca 100644
--- a/src/com/android/settings/NotificationStation.java
+++ b/src/com/android/settings/NotificationStation.java
@@ -25,11 +25,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -46,6 +48,7 @@
import com.android.internal.statusbar.StatusBarNotification;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
public class NotificationStation extends SettingsPreferenceFragment {
@@ -55,34 +58,57 @@
private static final boolean SHOW_HISTORICAL_NOTIFICATIONS = true;
private final PackageReceiver mPackageReceiver = new PackageReceiver();
-
+ private PackageManager mPm;
private INotificationManager mNoMan;
+
+ private Runnable mRefreshListRunnable = new Runnable() {
+ @Override
+ public void run() {
+ refreshList();
+ }
+ };
+
private INotificationListener.Stub mListener = new INotificationListener.Stub() {
@Override
public void onNotificationPosted(StatusBarNotification notification) throws RemoteException {
Log.v(TAG, "onNotificationPosted: " + notification);
- getListView().post(new Runnable() { public void run() { refreshList(); }});
+ final Handler h = getListView().getHandler();
+ h.removeCallbacks(mRefreshListRunnable);
+ h.postDelayed(mRefreshListRunnable, 100);
}
@Override
public void onNotificationRemoved(StatusBarNotification notification) throws RemoteException {
- Log.v(TAG, "onNotificationRemoved: " + notification);
- getListView().post(new Runnable() { public void run() { refreshList(); }});
+ final Handler h = getListView().getHandler();
+ h.removeCallbacks(mRefreshListRunnable);
+ h.postDelayed(mRefreshListRunnable, 100);
}
};
private NotificationHistoryAdapter mAdapter;
private Context mContext;
+ private final Comparator<HistoricalNotificationInfo> mNotificationSorter
+ = new Comparator<HistoricalNotificationInfo>() {
+ @Override
+ public int compare(HistoricalNotificationInfo lhs,
+ HistoricalNotificationInfo rhs) {
+ return (int)(rhs.timestamp - lhs.timestamp);
+ }
+ };
+
@Override
public void onAttach(Activity activity) {
logd("onAttach(%s)", activity.getClass().getSimpleName());
super.onAttach(activity);
mContext = activity;
+ mPm = mContext.getPackageManager();
mNoMan = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
try {
- mNoMan.registerListener(mListener, ActivityManager.getCurrentUser());
+ mNoMan.registerListener(mListener,
+ mContext.getPackageName(),
+ ActivityManager.getCurrentUser());
} catch (RemoteException e) {
// well, that didn't work out
}
@@ -144,6 +170,7 @@
logd("adding %d infos", infos.size());
mAdapter.clear();
mAdapter.addAll(infos);
+ mAdapter.sort(mNotificationSorter);
}
}
@@ -155,6 +182,7 @@
private static class HistoricalNotificationInfo {
public String pkg;
public Drawable pkgicon;
+ public CharSequence pkgname;
public Drawable icon;
public CharSequence title;
public int priority;
@@ -180,8 +208,19 @@
info.user = sbn.getUserId();
info.icon = loadIconDrawable(info.pkg, info.user, sbn.notification.icon);
info.pkgicon = loadPackageIconDrawable(info.pkg, info.user);
+ info.pkgname = loadPackageName(info.pkg);
if (sbn.notification.extras != null) {
info.title = sbn.notification.extras.getString(Notification.EXTRA_TITLE);
+ if (info.title == null || "".equals(info.title)) {
+ info.title = sbn.notification.extras.getString(Notification.EXTRA_TEXT);
+ }
+ }
+ if (info.title == null || "".equals(info.title)) {
+ info.title = sbn.notification.tickerText;
+ }
+ // still nothing? come on, give us something!
+ if (info.title == null || "".equals(info.title)) {
+ info.title = info.pkgname;
}
info.timestamp = sbn.postTime;
info.priority = sbn.notification.priority;
@@ -211,8 +250,7 @@
if (userId == UserHandle.USER_ALL) {
userId = UserHandle.USER_OWNER;
}
- r = mContext.getPackageManager()
- .getResourcesForApplicationAsUser(pkg, userId);
+ r = mPm.getResourcesForApplicationAsUser(pkg, userId);
} catch (PackageManager.NameNotFoundException ex) {
Log.e(TAG, "Icon package not found: " + pkg);
return null;
@@ -226,13 +264,23 @@
private Drawable loadPackageIconDrawable(String pkg, int userId) {
Drawable icon = null;
try {
- icon = mContext.getPackageManager().getApplicationIcon(pkg);
+ icon = mPm.getApplicationIcon(pkg);
} catch (PackageManager.NameNotFoundException e) {
}
return icon;
}
+ private CharSequence loadPackageName(String pkg) {
+ try {
+ ApplicationInfo info = mPm.getApplicationInfo(pkg,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ if (info != null) return mPm.getApplicationLabel(info);
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ return pkg;
+ }
+
private Drawable loadIconDrawable(String pkg, int userId, int resId) {
Resources r = getResourcesForUserPackage(pkg, userId);
@@ -261,9 +309,9 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- HistoricalNotificationInfo info = getItem(position);
+ final HistoricalNotificationInfo info = getItem(position);
logd("getView(%s/%s)", info.pkg, info.title);
- final View row = convertView != null ? convertView : createRow(parent, info.pkg);
+ final View row = convertView != null ? convertView : createRow(parent);
row.setTag(info);
// bind icon
@@ -279,8 +327,25 @@
// bind caption
((TextView) row.findViewById(android.R.id.title)).setText(info.title);
+ // app name
+ ((TextView) row.findViewById(R.id.pkgname)).setText(info.pkgname);
+
+ // extra goodies -- not implemented yet
+// ((TextView) row.findViewById(R.id.extra)).setText(
+// ...
+// );
+ row.findViewById(R.id.extra).setVisibility(View.GONE);
+
row.setAlpha(info.active ? 1.0f : 0.5f);
+ // set up click handler
+ row.setOnClickListener(new OnClickListener(){
+ @Override
+ public void onClick(View v) {
+ v.setPressed(true);
+ startApplicationDetailsActivity(info.pkg);
+ }});
+
// // bind radio button
// RadioButton radioButton = (RadioButton) row.findViewById(android.R.id.button1);
// radioButton.setChecked(dreamInfo.isActive);
@@ -310,14 +375,8 @@
return row;
}
- private View createRow(ViewGroup parent, final String pkg) {
+ private View createRow(ViewGroup parent) {
final View row = mInflater.inflate(R.layout.notification_log_row, parent, false);
- row.setOnClickListener(new OnClickListener(){
- @Override
- public void onClick(View v) {
- v.setPressed(true);
- startApplicationDetailsActivity(pkg);
- }});
return row;
}
@@ -326,7 +385,7 @@
private void startApplicationDetailsActivity(String packageName) {
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null));
- intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
+ intent.setComponent(intent.resolveActivity(mPm));
startActivity(intent);
}