diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 4d72f73cd3775..739aca35ff604 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -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; } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 3003580089da5..7a70c808293be 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -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)mActions.clone(); + } + return that; + } + public String getPackage() { return mPackage; } diff --git a/core/java/com/android/internal/statusbar/StatusBarIcon.java b/core/java/com/android/internal/statusbar/StatusBarIcon.java index 455e17bf5feb9..e28325c3b3865 100644 --- a/core/java/com/android/internal/statusbar/StatusBarIcon.java +++ b/core/java/com/android/internal/statusbar/StatusBarIcon.java @@ -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() { diff --git a/core/java/com/android/internal/statusbar/StatusBarNotification.java b/core/java/com/android/internal/statusbar/StatusBarNotification.java new file mode 100644 index 0000000000000..ba1525edf2923 --- /dev/null +++ b/core/java/com/android/internal/statusbar/StatusBarNotification.java @@ -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 CREATOR + = new Parcelable.Creator() + { + 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 + ")"; + } + +} + + diff --git a/services/java/com/android/server/status/StatusBarNotification.java b/core/java/com/android/internal/statusbar/StatusBarNotificationList.aidl similarity index 52% rename from services/java/com/android/server/status/StatusBarNotification.java rename to core/java/com/android/internal/statusbar/StatusBarNotificationList.aidl index 4bb8fdbf99051..10abeee94e157 100644 --- a/services/java/com/android/server/status/StatusBarNotification.java +++ b/core/java/com/android/internal/statusbar/StatusBarNotificationList.aidl @@ -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; -} diff --git a/core/java/com/android/internal/statusbar/StatusBarNotificationList.java b/core/java/com/android/internal/statusbar/StatusBarNotificationList.java new file mode 100644 index 0000000000000..2b70f5fd08f73 --- /dev/null +++ b/core/java/com/android/internal/statusbar/StatusBarNotificationList.java @@ -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 mEntries = new ArrayList(); + + public StatusBarNotificationList() { + } + + public StatusBarNotificationList(Parcel in) { + readFromParcel(in); + } + + public void readFromParcel(Parcel in) { + final int N = in.readInt(); + for (int i=0; i CREATOR + = new Parcelable.Creator() + { + 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 entries = mEntries; + final int N = entries.size(); + for (int i=0; i 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(); diff --git a/services/java/com/android/server/status/NotificationData.java b/services/java/com/android/server/status/NotificationData.java deleted file mode 100644 index 71f01cab2f0fb..0000000000000 --- a/services/java/com/android/server/status/NotificationData.java +++ /dev/null @@ -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 + ")"; - } -} diff --git a/services/java/com/android/server/status/NotificationViewList.java b/services/java/com/android/server/status/NotificationViewList.java deleted file mode 100644 index e18e9dd6abb37..0000000000000 --- a/services/java/com/android/server/status/NotificationViewList.java +++ /dev/null @@ -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 mOngoing = new ArrayList(); - private ArrayList mLatest = new ArrayList(); - - public NotificationViewList() { - } - - private static final int indexInList(ArrayList list, NotificationData n){ - final int N = list.size(); - for (int i=0; i= 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 notificationsForPackage(String packageName) { - ArrayList list = new ArrayList(); - int N = mOngoing.size(); - for (int i=0; i list, IBinder key) { - final int N = list.size(); - for (int i=0; i= 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 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 mDisableRecords = new ArrayList(); @@ -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 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