Checkpoint. Data structures for Notifications in place.
Change-Id: I146fb9bc1d349112541368e2c99a667821dfdf6e
This commit is contained in:
@@ -341,6 +341,44 @@ public class Notification implements Parcelable
|
||||
iconLevel = parcel.readInt();
|
||||
}
|
||||
|
||||
public Notification clone() {
|
||||
Notification that = new Notification();
|
||||
|
||||
that.when = this.when;
|
||||
that.icon = this.icon;
|
||||
that.number = this.number;
|
||||
|
||||
// PendingIntents are global, so there's no reason (or way) to clone them.
|
||||
that.contentIntent = this.contentIntent;
|
||||
that.deleteIntent = this.deleteIntent;
|
||||
|
||||
if (this.tickerText != null) {
|
||||
that.tickerText = this.tickerText.toString();
|
||||
}
|
||||
if (this.contentView != null) {
|
||||
that.contentView = this.contentView.clone();
|
||||
}
|
||||
that.iconLevel = that.iconLevel;
|
||||
that.sound = this.sound; // android.net.Uri is immutable
|
||||
that.audioStreamType = this.audioStreamType;
|
||||
|
||||
final long[] vibrate = this.vibrate;
|
||||
if (vibrate != null) {
|
||||
final int N = vibrate.length;
|
||||
final long[] vib = that.vibrate = new long[N];
|
||||
System.arraycopy(vibrate, 0, vib, 0, N);
|
||||
}
|
||||
|
||||
that.ledARGB = this.ledARGB;
|
||||
that.ledOnMS = this.ledOnMS;
|
||||
that.ledOffMS = this.ledOffMS;
|
||||
that.defaults = this.defaults;
|
||||
|
||||
that.flags = this.flags;
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
* Base class for all actions that can be performed on an
|
||||
* inflated view.
|
||||
*
|
||||
* SUBCLASSES MUST BE IMMUTABLE SO CLONE WORKS!!!!!
|
||||
*/
|
||||
private abstract static class Action implements Parcelable {
|
||||
public abstract void apply(View root) throws ActionException;
|
||||
@@ -568,6 +569,14 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
public RemoteViews clone() {
|
||||
final RemoteViews that = new RemoteViews(mPackage, mLayoutId);
|
||||
if (mActions != null) {
|
||||
that.mActions = (ArrayList<Action>)mActions.clone();
|
||||
}
|
||||
return that;
|
||||
}
|
||||
|
||||
public String getPackage() {
|
||||
return mPackage;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class StatusBarIcon implements Parcelable {
|
||||
public int iconId;
|
||||
public int iconLevel;
|
||||
public boolean visible = true;
|
||||
public int number;
|
||||
|
||||
private StatusBarIcon() {
|
||||
}
|
||||
@@ -39,12 +40,14 @@ public class StatusBarIcon implements Parcelable {
|
||||
|
||||
public String toString() {
|
||||
return "StatusBarIcon(pkg=" + this.iconPackage + " id=0x" + Integer.toHexString(this.iconId)
|
||||
+ " level=" + this.iconLevel + " visible=" + visible + ")";
|
||||
+ " level=" + this.iconLevel + " visible=" + visible
|
||||
+ " num=" + this.number + " )";
|
||||
}
|
||||
|
||||
public StatusBarIcon clone() {
|
||||
StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.iconId, this.iconLevel);
|
||||
that.visible = this.visible;
|
||||
that.number = this.number;
|
||||
return that;
|
||||
}
|
||||
|
||||
@@ -60,13 +63,14 @@ public class StatusBarIcon implements Parcelable {
|
||||
this.iconId = in.readInt();
|
||||
this.iconLevel = in.readInt();
|
||||
this.visible = in.readInt() != 0;
|
||||
this.number = in.readInt();
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(this.iconPackage);
|
||||
out.writeInt(this.iconId);
|
||||
out.writeInt(this.iconLevel);
|
||||
out.writeInt(this.visible ? 1 : 0);
|
||||
out.writeInt(this.number);
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.statusbar;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
|
||||
/*
|
||||
boolean clearable = !n.ongoingEvent && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
|
||||
|
||||
|
||||
// TODO: make this restriction do something smarter like never fill
|
||||
// more than two screens. "Why would anyone need more than 80 characters." :-/
|
||||
final int maxTickerLen = 80;
|
||||
if (truncatedTicker != null && truncatedTicker.length() > maxTickerLen) {
|
||||
truncatedTicker = truncatedTicker.subSequence(0, maxTickerLen);
|
||||
}
|
||||
*/
|
||||
|
||||
public class StatusBarNotification implements Parcelable {
|
||||
public String pkg;
|
||||
public int id;
|
||||
public String tag;
|
||||
Notification notification;
|
||||
|
||||
public StatusBarNotification() {
|
||||
}
|
||||
|
||||
public StatusBarNotification(String pkg, int id, String tag, Notification notification) {
|
||||
if (pkg == null) throw new NullPointerException();
|
||||
if (notification == null) throw new NullPointerException();
|
||||
|
||||
this.pkg = pkg;
|
||||
this.id = id;
|
||||
this.tag = tag;
|
||||
this.notification = notification;
|
||||
}
|
||||
|
||||
public StatusBarNotification(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public void readFromParcel(Parcel in) {
|
||||
this.pkg = in.readString();
|
||||
this.id = in.readInt();
|
||||
if (in.readInt() != 0) {
|
||||
this.tag = in.readString();
|
||||
} else {
|
||||
this.tag = null;
|
||||
}
|
||||
this.notification = new Notification(in);
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(this.pkg);
|
||||
out.writeInt(this.id);
|
||||
if (this.tag != null) {
|
||||
out.writeInt(1);
|
||||
out.writeString(this.tag);
|
||||
} else {
|
||||
out.writeInt(0);
|
||||
}
|
||||
this.notification.writeToParcel(out, flags);
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<StatusBarNotification> CREATOR
|
||||
= new Parcelable.Creator<StatusBarNotification>()
|
||||
{
|
||||
public StatusBarNotification createFromParcel(Parcel parcel)
|
||||
{
|
||||
return new StatusBarNotification(parcel);
|
||||
}
|
||||
|
||||
public StatusBarNotification[] newArray(int size)
|
||||
{
|
||||
return new StatusBarNotification[size];
|
||||
}
|
||||
};
|
||||
|
||||
public StatusBarNotification clone() {
|
||||
return new StatusBarNotification(this.pkg, this.id, this.tag, this.notification.clone());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "StatusBarNotification(package=" + pkg + " tag=" + tag
|
||||
+ " notification=" + notification + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (c) 2010, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.status;
|
||||
package com.android.internal.statusbar;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.view.View;
|
||||
parcelable StatusBarNotificationList;
|
||||
|
||||
public class StatusBarNotification {
|
||||
IBinder key;
|
||||
NotificationData data;
|
||||
View view;
|
||||
View contentView;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.internal.statusbar;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class StatusBarNotificationList implements Parcelable {
|
||||
private class Entry {
|
||||
IBinder key;
|
||||
public StatusBarNotification notification;
|
||||
|
||||
void writeToParcel(Parcel out, int flags) {
|
||||
out.writeStrongBinder(key);
|
||||
notification.writeToParcel(out, flags);
|
||||
}
|
||||
|
||||
void readFromParcel(Parcel in) {
|
||||
key = in.readStrongBinder();
|
||||
notification = new StatusBarNotification(in);
|
||||
}
|
||||
|
||||
public Entry clone() {
|
||||
Entry that = new Entry();
|
||||
that.key = this.key;
|
||||
that.notification = this.notification.clone();
|
||||
return that;
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Entry> mEntries = new ArrayList<Entry>();
|
||||
|
||||
public StatusBarNotificationList() {
|
||||
}
|
||||
|
||||
public StatusBarNotificationList(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public void readFromParcel(Parcel in) {
|
||||
final int N = in.readInt();
|
||||
for (int i=0; i<N; i++) {
|
||||
Entry e = new Entry();
|
||||
e.readFromParcel(in);
|
||||
mEntries.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
final int N = mEntries.size();
|
||||
out.writeInt(N);
|
||||
for (int i=0; i<N; i++) {
|
||||
mEntries.get(i).writeToParcel(out, flags);
|
||||
}
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parcelable.Creator that instantiates StatusBarNotificationList objects
|
||||
*/
|
||||
public static final Parcelable.Creator<StatusBarNotificationList> CREATOR
|
||||
= new Parcelable.Creator<StatusBarNotificationList>()
|
||||
{
|
||||
public StatusBarNotificationList createFromParcel(Parcel parcel)
|
||||
{
|
||||
return new StatusBarNotificationList(parcel);
|
||||
}
|
||||
|
||||
public StatusBarNotificationList[] newArray(int size)
|
||||
{
|
||||
return new StatusBarNotificationList[size];
|
||||
}
|
||||
};
|
||||
|
||||
public void copyFrom(StatusBarNotificationList that) {
|
||||
mEntries.clear();
|
||||
final int N = that.mEntries.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
mEntries.add(that.mEntries.get(i).clone());
|
||||
}
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
final int N = mEntries.size();
|
||||
pw.println("Notification list:");
|
||||
for (int i=0; i<N; i++) {
|
||||
Entry e = mEntries.get(i);
|
||||
pw.printf(" %2d: %s\n", i, e.notification.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int size() {
|
||||
return mEntries.size();
|
||||
}
|
||||
|
||||
public IBinder add(StatusBarNotification notification) {
|
||||
if (notification == null) throw new NullPointerException();
|
||||
|
||||
Entry entry = new Entry();
|
||||
entry.key = new Binder();
|
||||
entry.notification = notification.clone();
|
||||
|
||||
// TODO: Sort correctly by "when"
|
||||
mEntries.add(entry);
|
||||
|
||||
return entry.key;
|
||||
}
|
||||
|
||||
public void update(IBinder key, StatusBarNotification notification) {
|
||||
final int index = getIndex(key);
|
||||
if (index < 0) {
|
||||
throw new IllegalArgumentException("got invalid key: " + key);
|
||||
}
|
||||
final Entry entry = mEntries.get(index);
|
||||
entry.notification = notification.clone();
|
||||
}
|
||||
|
||||
public void remove(IBinder key) {
|
||||
final int index = getIndex(key);
|
||||
if (index < 0) {
|
||||
throw new IllegalArgumentException("got invalid key: " + key);
|
||||
}
|
||||
mEntries.remove(index);
|
||||
}
|
||||
|
||||
public int getIndex(IBinder key) {
|
||||
final ArrayList<Entry> entries = mEntries;
|
||||
final int N = entries.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (entries.get(i).key == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public StatusBarNotification getNotification(int index) {
|
||||
return mEntries.get(index).notification;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,6 +426,11 @@ public class PhoneStatusBarService extends StatusBarService {
|
||||
return row;
|
||||
}
|
||||
|
||||
/*
|
||||
StatusBarIcon icon = new StatusBarIcon(pkg, notification.icon,
|
||||
notification.iconLevel);
|
||||
icon.number = notification.number;
|
||||
*/
|
||||
void addNotificationView(StatusBarNotification notification) {
|
||||
if (notification.view != null) {
|
||||
throw new RuntimeException("Assertion failed: notification.view="
|
||||
|
||||
@@ -61,6 +61,7 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
&& mIcon.visible == icon.visible;
|
||||
if (!iconEquals) {
|
||||
setImageDrawable(getIcon(icon));
|
||||
// TODO: What if getIcon returns null?
|
||||
}
|
||||
if (!levelEquals) {
|
||||
setImageLevel(icon.iconLevel);
|
||||
|
||||
@@ -37,8 +37,6 @@ import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.internal.statusbar.StatusBarIconList;
|
||||
|
||||
import com.android.server.status.NotificationData;
|
||||
|
||||
public abstract class StatusBarService extends Service implements CommandQueue.Callbacks {
|
||||
private static final String TAG = "StatusBarService";
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.android.server;
|
||||
|
||||
import com.android.server.status.IconData;
|
||||
import com.android.server.status.NotificationData;
|
||||
import com.android.internal.statusbar.StatusBarNotification;
|
||||
import com.android.server.status.StatusBarManagerService;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
@@ -705,36 +705,12 @@ class NotificationManagerService extends INotificationManager.Stub
|
||||
}
|
||||
|
||||
if (notification.icon != 0) {
|
||||
IconData icon = IconData.makeIcon(null, pkg, notification.icon,
|
||||
notification.iconLevel,
|
||||
notification.number);
|
||||
CharSequence truncatedTicker = notification.tickerText;
|
||||
|
||||
// TODO: make this restriction do something smarter like never fill
|
||||
// more than two screens. "Why would anyone need more than 80 characters." :-/
|
||||
final int maxTickerLen = 80;
|
||||
if (truncatedTicker != null && truncatedTicker.length() > maxTickerLen) {
|
||||
truncatedTicker = truncatedTicker.subSequence(0, maxTickerLen);
|
||||
}
|
||||
|
||||
NotificationData n = new NotificationData();
|
||||
n.pkg = pkg;
|
||||
n.tag = tag;
|
||||
n.id = id;
|
||||
n.when = notification.when;
|
||||
n.tickerText = truncatedTicker;
|
||||
n.ongoingEvent = (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
|
||||
if (!n.ongoingEvent && (notification.flags & Notification.FLAG_NO_CLEAR) == 0) {
|
||||
n.clearable = true;
|
||||
}
|
||||
n.contentView = notification.contentView;
|
||||
n.contentIntent = notification.contentIntent;
|
||||
n.deleteIntent = notification.deleteIntent;
|
||||
StatusBarNotification n = new StatusBarNotification(pkg, id, tag, notification);
|
||||
if (old != null && old.statusBarKey != null) {
|
||||
r.statusBarKey = old.statusBarKey;
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mStatusBar.updateNotification(r.statusBarKey, icon, n);
|
||||
mStatusBar.updateNotification(r.statusBarKey, n);
|
||||
}
|
||||
finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
@@ -742,16 +718,14 @@ class NotificationManagerService extends INotificationManager.Stub
|
||||
} else {
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
r.statusBarKey = mStatusBar.addNotification(icon, n);
|
||||
r.statusBarKey = mStatusBar.addNotification(n);
|
||||
mAttentionLight.pulse();
|
||||
}
|
||||
finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
sendAccessibilityEvent(notification, pkg);
|
||||
|
||||
} else {
|
||||
if (old != null && old.statusBarKey != null) {
|
||||
long identity = Binder.clearCallingIdentity();
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.status;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
public class NotificationData {
|
||||
public String pkg;
|
||||
public String tag;
|
||||
public int id;
|
||||
public CharSequence tickerText;
|
||||
|
||||
public long when;
|
||||
public boolean ongoingEvent;
|
||||
public boolean clearable;
|
||||
|
||||
public RemoteViews contentView;
|
||||
public PendingIntent contentIntent;
|
||||
|
||||
public PendingIntent deleteIntent;
|
||||
|
||||
public String toString() {
|
||||
return "NotificationData(package=" + pkg + " id=" + id + " tickerText=" + tickerText
|
||||
+ " ongoingEvent=" + ongoingEvent + " contentIntent=" + contentIntent
|
||||
+ " deleteIntent=" + deleteIntent
|
||||
+ " clearable=" + clearable
|
||||
+ " contentView=" + contentView + " when=" + when + ")";
|
||||
}
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.status;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.util.Slog;
|
||||
import android.view.View;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class NotificationViewList {
|
||||
private ArrayList<StatusBarNotification> mOngoing = new ArrayList();
|
||||
private ArrayList<StatusBarNotification> mLatest = new ArrayList();
|
||||
|
||||
public NotificationViewList() {
|
||||
}
|
||||
|
||||
private static final int indexInList(ArrayList<StatusBarNotification> list, NotificationData n){
|
||||
final int N = list.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
StatusBarNotification that = list.get(i);
|
||||
if (that.data == n) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int getIconIndex(NotificationData n) {
|
||||
final int ongoingSize = mOngoing.size();
|
||||
final int latestSize = mLatest.size();
|
||||
if (n.ongoingEvent) {
|
||||
int index = indexInList(mOngoing, n);
|
||||
if (index >= 0) {
|
||||
return latestSize + index + 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return indexInList(mLatest, n) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void remove(StatusBarNotification notification) {
|
||||
NotificationData n = notification.data;
|
||||
int index;
|
||||
index = indexInList(mOngoing, n);
|
||||
if (index >= 0) {
|
||||
mOngoing.remove(index);
|
||||
return;
|
||||
}
|
||||
index = indexInList(mLatest, n);
|
||||
if (index >= 0) {
|
||||
mLatest.remove(index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<StatusBarNotification> notificationsForPackage(String packageName) {
|
||||
ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>();
|
||||
int N = mOngoing.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (matchPackage(mOngoing.get(i), packageName)) {
|
||||
list.add(mOngoing.get(i));
|
||||
}
|
||||
}
|
||||
N = mLatest.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (matchPackage(mLatest.get(i), packageName)) {
|
||||
list.add(mLatest.get(i));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private final boolean matchPackage(StatusBarNotification snb, String packageName) {
|
||||
if (snb.data.contentIntent != null) {
|
||||
if (snb.data.contentIntent.getTargetPackage().equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
} else if (snb.data.pkg != null && snb.data.pkg.equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final int indexForKey(ArrayList<StatusBarNotification> list, IBinder key) {
|
||||
final int N = list.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (list.get(i).key == key) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
StatusBarNotification get(IBinder key) {
|
||||
int index;
|
||||
index = indexForKey(mOngoing, key);
|
||||
if (index >= 0) {
|
||||
return mOngoing.get(index);
|
||||
}
|
||||
index = indexForKey(mLatest, key);
|
||||
if (index >= 0) {
|
||||
return mLatest.get(index);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// gets the index of the notification's view in its expanded parent view
|
||||
int getExpandedIndex(StatusBarNotification notification) {
|
||||
ArrayList<StatusBarNotification> list = notification.data.ongoingEvent ? mOngoing : mLatest;
|
||||
final IBinder key = notification.key;
|
||||
int index = 0;
|
||||
// (the view order is backwards from this list order)
|
||||
for (int i=list.size()-1; i>=0; i--) {
|
||||
StatusBarNotification item = list.get(i);
|
||||
if (item.key == key) {
|
||||
return index;
|
||||
}
|
||||
if (item.view != null) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
Slog.e(StatusBarManagerService.TAG, "Couldn't find notification in NotificationViewList.");
|
||||
Slog.e(StatusBarManagerService.TAG, "notification=" + notification);
|
||||
dump(notification);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clearViews() {
|
||||
int N = mOngoing.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
mOngoing.get(i).view = null;
|
||||
}
|
||||
N = mLatest.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
mLatest.get(i).view = null;
|
||||
}
|
||||
}
|
||||
|
||||
int ongoingCount() {
|
||||
return mOngoing.size();
|
||||
}
|
||||
|
||||
int latestCount() {
|
||||
return mLatest.size();
|
||||
}
|
||||
|
||||
StatusBarNotification getOngoing(int index) {
|
||||
return mOngoing.get(index);
|
||||
}
|
||||
|
||||
StatusBarNotification getLatest(int index) {
|
||||
return mLatest.get(index);
|
||||
}
|
||||
|
||||
int size() {
|
||||
return mOngoing.size() + mLatest.size();
|
||||
}
|
||||
|
||||
void add(StatusBarNotification notification) {
|
||||
if (StatusBarManagerService.SPEW) {
|
||||
Slog.d(StatusBarManagerService.TAG, "before add NotificationViewList"
|
||||
+ " notification.data.ongoingEvent=" + notification.data.ongoingEvent);
|
||||
dump(notification);
|
||||
}
|
||||
|
||||
ArrayList<StatusBarNotification> list = notification.data.ongoingEvent ? mOngoing : mLatest;
|
||||
long when = notification.data.when;
|
||||
final int N = list.size();
|
||||
int index = N;
|
||||
for (int i=0; i<N; i++) {
|
||||
StatusBarNotification that = list.get(i);
|
||||
if (that.data.when > when) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
list.add(index, notification);
|
||||
|
||||
if (StatusBarManagerService.SPEW) {
|
||||
Slog.d(StatusBarManagerService.TAG, "after add NotificationViewList index=" + index);
|
||||
dump(notification);
|
||||
}
|
||||
}
|
||||
|
||||
void dump(StatusBarNotification notification) {
|
||||
if (StatusBarManagerService.SPEW) {
|
||||
boolean showTime = false;
|
||||
String s = "";
|
||||
for (int i=0; i<mOngoing.size(); i++) {
|
||||
StatusBarNotification that = mOngoing.get(i);
|
||||
if (that.key == notification.key) {
|
||||
s += "[";
|
||||
}
|
||||
if (showTime) {
|
||||
s += that.data.when;
|
||||
} else {
|
||||
s += that.data.pkg + "/" + that.data.id + "/" + that.view;
|
||||
}
|
||||
if (that.key == notification.key) {
|
||||
s += "]";
|
||||
}
|
||||
s += " ";
|
||||
}
|
||||
Slog.d(StatusBarManagerService.TAG, "NotificationViewList ongoing: " + s);
|
||||
|
||||
s = "";
|
||||
for (int i=0; i<mLatest.size(); i++) {
|
||||
StatusBarNotification that = mLatest.get(i);
|
||||
if (that.key == notification.key) {
|
||||
s += "[";
|
||||
}
|
||||
if (showTime) {
|
||||
s += that.data.when;
|
||||
} else {
|
||||
s += that.data.pkg + "/" + that.data.id + "/" + that.view;
|
||||
}
|
||||
if (that.key == notification.key) {
|
||||
s += "]";
|
||||
}
|
||||
s += " ";
|
||||
}
|
||||
Slog.d(StatusBarManagerService.TAG, "NotificationViewList latest: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
StatusBarNotification get(View view) {
|
||||
int N = mOngoing.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
StatusBarNotification notification = mOngoing.get(i);
|
||||
View v = notification.view;
|
||||
if (v == view) {
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
N = mLatest.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
StatusBarNotification notification = mLatest.get(i);
|
||||
View v = notification.view;
|
||||
if (v == view) {
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void update(StatusBarNotification notification) {
|
||||
remove(notification);
|
||||
add(notification);
|
||||
}
|
||||
|
||||
boolean hasClearableItems() {
|
||||
int N = mLatest.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (mLatest.get(i).data.clearable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,8 @@ import com.android.internal.statusbar.IStatusBar;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.internal.statusbar.StatusBarIconList;
|
||||
import com.android.internal.statusbar.StatusBarNotification;
|
||||
import com.android.internal.statusbar.StatusBarNotificationList;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -60,10 +62,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
||||
NotificationCallbacks mNotificationCallbacks;
|
||||
volatile IStatusBar mBar;
|
||||
StatusBarIconList mIcons = new StatusBarIconList();
|
||||
private UninstallReceiver mUninstallReceiver;
|
||||
|
||||
// expanded notifications
|
||||
NotificationViewList mNotificationData = new NotificationViewList();
|
||||
StatusBarNotificationList mNotifications = new StatusBarNotificationList();
|
||||
|
||||
// for disabling the status bar
|
||||
ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
|
||||
@@ -93,7 +92,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
||||
*/
|
||||
public StatusBarManagerService(Context context) {
|
||||
mContext = context;
|
||||
mUninstallReceiver = new UninstallReceiver();
|
||||
|
||||
final Resources res = context.getResources();
|
||||
mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.status_bar_icon_order));
|
||||
@@ -266,15 +264,29 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
||||
Slog.d(TAG, "visibilityChanged visible=" + visible);
|
||||
}
|
||||
|
||||
public IBinder addNotification(IconData iconData, NotificationData notificationData) {
|
||||
return new Binder();
|
||||
// ================================================================================
|
||||
// Callbacks for NotificationManagerService.
|
||||
// ================================================================================
|
||||
public IBinder addNotification(StatusBarNotification notification) {
|
||||
synchronized (mNotifications) {
|
||||
IBinder key = mNotifications.add(notification);
|
||||
// TODO: tell mBar
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateNotification(IBinder key, IconData iconData,
|
||||
NotificationData notificationData) {
|
||||
public void updateNotification(IBinder key, StatusBarNotification notification) {
|
||||
synchronized (mNotifications) {
|
||||
mNotifications.update(key, notification);
|
||||
// TODO: tell mBar
|
||||
}
|
||||
}
|
||||
|
||||
public void removeNotification(IBinder key) {
|
||||
synchronized (mNotifications) {
|
||||
mNotifications.remove(key);
|
||||
// TODO: tell mBar
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================
|
||||
@@ -336,12 +348,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
||||
// Always called from UI thread
|
||||
// ================================================================================
|
||||
|
||||
StatusBarNotification getNotification(IBinder key) {
|
||||
synchronized (mNotificationData) {
|
||||
return mNotificationData.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
@@ -354,23 +360,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
||||
synchronized (mIcons) {
|
||||
mIcons.dump(pw);
|
||||
}
|
||||
|
||||
synchronized (mNotificationData) {
|
||||
int N = mNotificationData.ongoingCount();
|
||||
pw.println(" ongoingCount.size=" + N);
|
||||
for (int i=0; i<N; i++) {
|
||||
StatusBarNotification n = mNotificationData.getOngoing(i);
|
||||
pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
|
||||
pw.println(" data=" + n.data);
|
||||
}
|
||||
N = mNotificationData.latestCount();
|
||||
pw.println(" ongoingCount.size=" + N);
|
||||
for (int i=0; i<N; i++) {
|
||||
StatusBarNotification n = mNotificationData.getLatest(i);
|
||||
pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
|
||||
pw.println(" data=" + n.data);
|
||||
}
|
||||
|
||||
synchronized (mNotifications) {
|
||||
mNotifications.dump(pw);
|
||||
}
|
||||
|
||||
synchronized (mDisableRecords) {
|
||||
final int N = mDisableRecords.size();
|
||||
pw.println(" mDisableRecords.size=" + N
|
||||
@@ -422,47 +416,4 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class UninstallReceiver extends BroadcastReceiver {
|
||||
public UninstallReceiver() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
|
||||
filter.addDataScheme("package");
|
||||
mContext.registerReceiver(this, filter);
|
||||
IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
|
||||
mContext.registerReceiver(this, sdFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String pkgList[] = null;
|
||||
if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
|
||||
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
|
||||
} else {
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
String pkg = data.getSchemeSpecificPart();
|
||||
if (pkg != null) {
|
||||
pkgList = new String[]{pkg};
|
||||
}
|
||||
}
|
||||
}
|
||||
ArrayList<StatusBarNotification> list = null;
|
||||
if (pkgList != null) {
|
||||
synchronized (StatusBarManagerService.this) {
|
||||
for (String pkg : pkgList) {
|
||||
list = mNotificationData.notificationsForPackage(pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list != null) {
|
||||
final int N = list.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
// TODO: removeIcon(list.get(i).key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user