summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/Settings.java18
-rw-r--r--packages/SystemUI/res/drawable-hdpi/spinner_default_holo_dark_am_no_underline.9.pngbin0 -> 408 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.pngbin0 -> 745 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.pngbin0 -> 614 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/spinner_default_holo_dark_am_no_underline.9.pngbin0 -> 293 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.pngbin0 -> 522 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.pngbin0 -> 444 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/spinner_default_holo_dark_am_no_underline.9.pngbin0 -> 404 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.pngbin0 -> 989 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.pngbin0 -> 765 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/spinner_default_holo_dark_am_no_underline.9.pngbin0 -> 456 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.pngbin0 -> 1639 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.pngbin0 -> 1144 bytes
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml6
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml6
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHeaderView.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java764
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java145
-rw-r--r--services/core/java/com/android/server/notification/NotificationDelegate.java3
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java131
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java28
25 files changed, 1239 insertions, 71 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 18018e2..40bbbd4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6082,6 +6082,24 @@ public final class Settings {
"lock_screen_show_notifications";
/**
+ * Defines global zen mode. One of ZEN_MODE_OFF, ZEN_MODE_LIMITED, ZEN_MODE_FULL.
+ *
+ * @hide
+ */
+ public static final String ZEN_MODE = "zen_mode";
+
+ /** @hide */ public static final int ZEN_MODE_OFF = 0;
+ /** @hide */ public static final int ZEN_MODE_LIMITED = 1;
+ /** @hide */ public static final int ZEN_MODE_FULL = 2;
+
+ /** @hide */ public static String zenModeToString(int mode) {
+ if (mode == ZEN_MODE_OFF) return "ZEN_MODE_OFF";
+ if (mode == ZEN_MODE_LIMITED) return "ZEN_MODE_LIMITED";
+ if (mode == ZEN_MODE_FULL) return "ZEN_MODE_FULL";
+ throw new IllegalArgumentException("Invalid zen mode: " + mode);
+ }
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
diff --git a/packages/SystemUI/res/drawable-hdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-hdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..267e7ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..fa23e85
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..aa8635c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-mdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..db51f6b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..b0185a5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..949ab10
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-xhdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..8d22ce2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..7f7cb63
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..abdeb3b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-xxhdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..29fb50f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..afe85b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..5e5053f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index eb66908..ea6be1b 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -62,7 +62,11 @@
android:src="@drawable/stat_notify_more"
android:visibility="gone"
/>
-
+ <com.android.systemui.statusbar.StatusBarIconView android:id="@+id/modeIcon"
+ android:layout_width="@dimen/status_bar_icon_size"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ />
<com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1693e01..56c1f4e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -58,6 +58,12 @@
android:layout_height="@dimen/notification_panel_header_height"
/>
+ <com.android.systemui.statusbar.phone.ZenModeView
+ android:id="@+id/zenmode"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+
<TextView
android:id="@+id/emergency_calls_only"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 9aa7cfd..25c516b 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -15,7 +15,7 @@
** limitations under the License.
-->
-<LinearLayout
+<com.android.systemui.statusbar.phone.PanelHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/header"
@@ -106,4 +106,4 @@
android:contentDescription="@string/accessibility_notifications_button"
/>
</FrameLayout>
-</LinearLayout>
+</com.android.systemui.statusbar.phone.PanelHeaderView>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7ff52de..5f62554 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -104,6 +104,9 @@ public abstract class BaseStatusBar extends SystemUI implements
public static final int EXPANDED_LEAVE_ALONE = -10000;
public static final int EXPANDED_FULL_OPEN = -10001;
+ private static final String EXTRA_INTERCEPT = "android.intercept";
+ private static final float INTERCEPTED_ALPHA = .2f;
+
protected CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
protected H mHandler = createHandler();
@@ -155,6 +158,8 @@ public abstract class BaseStatusBar extends SystemUI implements
private RecentsComponent mRecents;
+ protected int mZenMode;
+
public IStatusBarService getStatusBarService() {
return mBarService;
}
@@ -163,7 +168,7 @@ public abstract class BaseStatusBar extends SystemUI implements
return mDeviceProvisioned;
}
- private final ContentObserver mProvisioningObserver = new ContentObserver(mHandler) {
+ protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
final boolean provisioned = 0 != Settings.Global.getInt(
@@ -172,6 +177,9 @@ public abstract class BaseStatusBar extends SystemUI implements
mDeviceProvisioned = provisioned;
updateNotificationIcons();
}
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+ setZenMode(mode);
}
};
@@ -239,10 +247,13 @@ public abstract class BaseStatusBar extends SystemUI implements
ServiceManager.checkService(DreamService.DREAM_SERVICE));
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mProvisioningObserver.onChange(false); // set up
+ mSettingsObserver.onChange(false); // set up
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
- mProvisioningObserver);
+ mSettingsObserver);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
+ mSettingsObserver);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
@@ -980,6 +991,7 @@ public abstract class BaseStatusBar extends SystemUI implements
if (DEBUG) {
Log.d(TAG, "addNotificationViews: added at " + pos);
}
+ updateInterceptedState(entry);
updateExpansionStates();
updateNotificationIcons();
}
@@ -1010,6 +1022,34 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
+ protected void setZenMode(int mode) {
+ final boolean change = mZenMode != mode;
+ mZenMode = mode;
+ final int N = mNotificationData.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationData.Entry entry = mNotificationData.get(i);
+ if (change && !shouldIntercept()) {
+ entry.notification.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
+ }
+ updateInterceptedState(entry);
+ }
+ updateNotificationIcons();
+ }
+
+ private boolean shouldIntercept() {
+ return mZenMode == Settings.Global.ZEN_MODE_LIMITED
+ || mZenMode == Settings.Global.ZEN_MODE_FULL;
+ }
+
+ protected boolean shouldIntercept(Notification n) {
+ return shouldIntercept() && n.extras.getBoolean(EXTRA_INTERCEPT);
+ }
+
+ private void updateInterceptedState(NotificationData.Entry entry) {
+ final boolean intercepted = shouldIntercept(entry.notification.getNotification());
+ entry.row.findViewById(R.id.container).setAlpha(intercepted ? INTERCEPTED_ALPHA : 1);
+ }
+
protected abstract void haltTicker();
protected abstract void setAreThereNotifications();
protected abstract void updateNotificationIcons();
@@ -1202,6 +1242,7 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
entry.content.setOnClickListener(null);
}
+ updateInterceptedState(entry);
}
protected void notifyHeadsUpScreenOn(boolean screenOn) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6be6d4d..ae74407 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -56,6 +56,10 @@ public class NotificationPanelView extends PanelView {
mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
mHandleView = findViewById(R.id.handle);
+ PanelHeaderView header = (PanelHeaderView) findViewById(R.id.header);
+ ZenModeView zenModeView = (ZenModeView) findViewById(R.id.zenmode);
+ zenModeView.setAdapter( new ZenModeViewAdapter(mContext));
+ header.setZenModeView(zenModeView);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHeaderView.java
new file mode 100644
index 0000000..a28324d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHeaderView.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 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.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.LinearLayout;
+
+public class PanelHeaderView extends LinearLayout {
+ private static final String TAG = "PanelHeaderView";
+ private static final boolean DEBUG = false;
+
+ private ZenModeView mZenModeView;
+
+ public PanelHeaderView(Context context) {
+ super(context);
+ }
+
+ public PanelHeaderView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setZenModeView(ZenModeView zmv) {
+ mZenModeView = zmv;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ final boolean rt = super.dispatchTouchEvent(ev);
+ if (DEBUG) logTouchEvent("dispatchTouchEvent", rt, ev);
+ if (mZenModeView != null) {
+ mZenModeView.dispatchExternalTouchEvent(ev);
+ }
+ return rt;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ final boolean rt = super.onInterceptTouchEvent(ev);
+ if (DEBUG) logTouchEvent("onInterceptTouchEvent", rt, ev);
+ return rt;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean rt = super.onTouchEvent(event);
+ if (DEBUG) logTouchEvent("onTouchEvent", rt, event);
+ return true;
+ }
+
+ private void logTouchEvent(String method, boolean rt, MotionEvent ev) {
+ Log.d(TAG, method + " " + (rt ? "TRUE" : "FALSE") + " " + ev);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2114991..631a1ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -189,6 +189,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
IconMerger mNotificationIcons;
// [+>
View mMoreIcon;
+ // mode indicator icon
+ ImageView mModeIcon;
// expanded notifications
NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -341,6 +343,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
}};
@Override
+ public void setZenMode(int mode) {
+ super.setZenMode(mode);
+ if (mModeIcon == null) return;
+ final boolean limited = mode == Settings.Global.ZEN_MODE_LIMITED;
+ final boolean full = mode == Settings.Global.ZEN_MODE_FULL;
+ mModeIcon.setVisibility(full || limited ? View.VISIBLE : View.GONE);
+ final int icon = limited ? R.drawable.stat_sys_zen_limited : R.drawable.stat_sys_zen_full;
+ if (full || limited) {
+ mModeIcon.setImageResource(icon);
+ }
+ }
+
+ @Override
public void start() {
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
@@ -352,6 +367,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext);
+ mSettingsObserver.onChange(false); // set up
mHeadsUpObserver.onChange(true); // set up
if (ENABLE_HEADS_UP) {
@@ -455,6 +471,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
+ mModeIcon = (ImageView)mStatusBarView.findViewById(R.id.modeIcon);
mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
mTickerView = mStatusBarView.findViewById(R.id.ticker);
@@ -909,41 +926,43 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
if (shadeEntry == null) {
return;
}
- if (mUseHeadsUp && shouldInterrupt(notification)) {
- if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
- Entry interruptionCandidate = new Entry(key, notification, null);
- ViewGroup holder = mHeadsUpNotificationView.getHolder();
- if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
- mInterruptingNotificationTime = System.currentTimeMillis();
- mInterruptingNotificationEntry = interruptionCandidate;
- shadeEntry.setInterruption();
+ if (!shouldIntercept(notification.getNotification())) {
+ if (mUseHeadsUp && shouldInterrupt(notification)) {
+ if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
+ Entry interruptionCandidate = new Entry(key, notification, null);
+ ViewGroup holder = mHeadsUpNotificationView.getHolder();
+ if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
+ mInterruptingNotificationTime = System.currentTimeMillis();
+ mInterruptingNotificationEntry = interruptionCandidate;
+ shadeEntry.setInterruption();
- // 1. Populate mHeadsUpNotificationView
- mHeadsUpNotificationView.setNotification(mInterruptingNotificationEntry);
+ // 1. Populate mHeadsUpNotificationView
+ mHeadsUpNotificationView.setNotification(mInterruptingNotificationEntry);
- // 2. Animate mHeadsUpNotificationView in
- mHandler.sendEmptyMessage(MSG_SHOW_HEADS_UP);
+ // 2. Animate mHeadsUpNotificationView in
+ mHandler.sendEmptyMessage(MSG_SHOW_HEADS_UP);
- // 3. Set alarm to age the notification off
- resetHeadsUpDecayTimer();
- }
- } else if (notification.getNotification().fullScreenIntent != null) {
- // Stop screensaver if the notification has a full-screen intent.
- // (like an incoming phone call)
- awakenDreams();
+ // 3. Set alarm to age the notification off
+ resetHeadsUpDecayTimer();
+ }
+ } else if (notification.getNotification().fullScreenIntent != null) {
+ // Stop screensaver if the notification has a full-screen intent.
+ // (like an incoming phone call)
+ awakenDreams();
- // not immersive & a full-screen alert should be shown
- if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
- try {
- notification.getNotification().fullScreenIntent.send();
- } catch (PendingIntent.CanceledException e) {
- }
- } else {
- // usual case: status bar visible & not immersive
+ // not immersive & a full-screen alert should be shown
+ if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
+ try {
+ notification.getNotification().fullScreenIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ }
+ } else {
+ // usual case: status bar visible & not immersive
- // show the ticker if there isn't already a heads up
- if (mInterruptingNotificationEntry == null) {
- tick(null, notification, true);
+ // show the ticker if there isn't already a heads up
+ if (mInterruptingNotificationEntry == null) {
+ tick(null, notification, true);
+ }
}
}
addNotificationViews(shadeEntry);
@@ -1096,6 +1115,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
// in "public" mode (atop a secure keyguard), secret notifs are totally hidden
continue;
}
+ if (shouldIntercept(ent.notification.getNotification())) {
+ continue;
+ }
toShow.add(ent.icon);
}
@@ -2183,6 +2205,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
pw.println(windowStateToString(mStatusBarWindowState));
pw.print(" mStatusBarMode=");
pw.println(BarTransitions.modeToString(mStatusBarMode));
+ pw.print(" mZenMode=");
+ pw.println(Settings.Global.zenModeToString(mZenMode));
dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
if (mNavigationBarView != null) {
pw.print(" mNavigationBarWindowState=");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
new file mode 100644
index 0000000..a89dacf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -0,0 +1,764 @@
+/*
+ * Copyright (C) 2014 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.systemui.statusbar.phone;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.PathShape;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.TextPaint;
+import android.text.method.LinkMovementMethod;
+import android.text.style.RelativeSizeSpan;
+import android.text.style.URLSpan;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.PopupWindow;
+import android.widget.RelativeLayout;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.ZenModeView.Adapter.ExitCondition;
+
+public class ZenModeView extends RelativeLayout {
+ private static final String TAG = ZenModeView.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private static final Typeface CONDENSED =
+ Typeface.create("sans-serif-condensed", Typeface.NORMAL);
+ private static final int GRAY = 0xff999999; //TextAppearance.StatusBar.Expanded.Network
+ private static final int BACKGROUND = 0xff1d3741; //0x3333b5e5;
+ private static final long DURATION = new ValueAnimator().getDuration();
+ private static final long BOUNCE_DURATION = DURATION / 3;
+ private static final float BOUNCE_SCALE = 0.8f;
+ private static final float SETTINGS_ALPHA = 0.6f;
+ private static final int INFO_WINDOW_DELAY = 2000;
+
+ private static final String LIMITED_TEXT =
+ "New notifications suppressed except calls, alarms & timers.";
+ private static final String FULL_TEXT =
+ "You won't hear any calls, alarms or timers.";
+
+ private final Context mContext;
+ private final Paint mPathPaint;
+ private final TextView mHintText;
+ private final ModeSpinner mModeSpinner;
+ private final ImageView mCloseButton;
+ private final ImageView mSettingsButton;
+ private final InfoWindow mInfoWindow;
+ private final Rect mLayoutRect = new Rect();
+ private final UntilPager mUntilPager;
+ private final AlarmWarning mAlarmWarning;
+
+ private float mDownY;
+ private int mDownBottom;
+ private boolean mPeekable = true;
+ private boolean mClosing;
+ private int mBottom;
+ private int mWidthSpec;
+ private Adapter mAdapter;
+
+ public ZenModeView(Context context) {
+ this(context, null);
+ }
+
+ public ZenModeView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ if (DEBUG) log("new %s()", getClass().getSimpleName());
+ mContext = context;
+
+ mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mPathPaint.setStyle(Paint.Style.STROKE);
+ mPathPaint.setColor(GRAY);
+ mPathPaint.setStrokeWidth(5);
+
+ final int iconSize = mContext.getResources()
+ .getDimensionPixelSize(com.android.internal.R.dimen.notification_large_icon_width);
+ final int topRowSize = iconSize * 2 / 3;
+
+ mCloseButton = new ImageView(mContext);
+ mCloseButton.setAlpha(0f);
+ mCloseButton.setImageDrawable(sd(closePath(topRowSize), topRowSize, mPathPaint));
+ addView(mCloseButton, new LayoutParams(topRowSize, topRowSize));
+ mCloseButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ bounce(v, null);
+ close();
+ }
+ });
+
+ mSettingsButton = new ImageView(mContext);
+ mSettingsButton.setAlpha(0f);
+ final int p = topRowSize / 7;
+ mSettingsButton.setPadding(p, p, p, p);
+ mSettingsButton.setImageResource(R.drawable.ic_notify_settings_normal);
+ LayoutParams lp = new LayoutParams(topRowSize, topRowSize);
+ lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ addView(mSettingsButton, lp);
+ mSettingsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mAdapter == null || mAdapter.getMode() != Adapter.MODE_LIMITED) {
+ return;
+ }
+ if (!mInfoWindow.isShowing()) {
+ mInfoWindow.show(mUntilPager);
+ }
+ bounce(mSettingsButton, null);
+ }
+ });
+ mInfoWindow = new InfoWindow(mContext, LIMITED_TEXT);
+
+ mModeSpinner = new ModeSpinner(mContext);
+ mModeSpinner.setAlpha(0);
+ mModeSpinner.setEnabled(false);
+ mModeSpinner.setId(android.R.id.title);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
+ lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
+ addView(mModeSpinner, lp);
+
+
+ mUntilPager = new UntilPager(mContext, mPathPaint, iconSize);
+ mUntilPager.setId(android.R.id.tabhost);
+ mUntilPager.setAlpha(0);
+ lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ lp.addRule(BELOW, mModeSpinner.getId());
+ addView(mUntilPager, lp);
+
+ mAlarmWarning = new AlarmWarning(mContext);
+ mAlarmWarning.setAlpha(0);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ lp.addRule(CENTER_HORIZONTAL);
+ lp.addRule(BELOW, mUntilPager.getId());
+ addView(mAlarmWarning, lp);
+
+ mHintText = new TextView(mContext);
+ mHintText.setTypeface(CONDENSED);
+ mHintText.setText("Swipe down for Limited Interruptions");
+ mHintText.setGravity(Gravity.CENTER);
+ mHintText.setTextColor(GRAY);
+ addView(mHintText, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+ }
+
+ private void close() {
+ mClosing = true;
+ final int startBottom = mBottom;
+ final int max = mPeekable ? getExpandedBottom() : startBottom;
+ mHintText.animate().alpha(1).setUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float f = animation.getAnimatedFraction();
+ final int hintBottom = mHintText.getBottom();
+ setPeeked(hintBottom + (int)((1-f) * (startBottom - hintBottom)), max);
+ if (f == 1) {
+ mPeekable = true;
+ mClosing = false;
+ mModeSpinner.updateState();
+ if (mAdapter != null) {
+ mAdapter.cancel();
+ }
+ }
+ }
+ }).start();
+ mUntilPager.animate().alpha(0).start();
+ mAlarmWarning.animate().alpha(0).start();
+ mInfoWindow.dismiss();
+ }
+
+ public void setAdapter(Adapter adapter) {
+ mAdapter = adapter;
+ mAdapter.setCallbacks(new Adapter.Callbacks() {
+ @Override
+ public void onChanged() {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ updateState(true);
+ }
+ });
+ }
+ });
+ updateState(false);
+ }
+
+ private void updateState(boolean animate) {
+ if (mAdapter != null && mAdapter.getMode() == Adapter.MODE_OFF && !mPeekable) {
+ close();
+ } else {
+ mModeSpinner.updateState();
+ mUntilPager.updateState();
+ mAlarmWarning.updateState(animate);
+ final float settingsAlpha = getSettingsButtonAlpha();
+ if (settingsAlpha != mSettingsButton.getAlpha()) {
+ if (animate) {
+ mSettingsButton.animate().alpha(settingsAlpha).start();
+ } else {
+ mSettingsButton.setAlpha(settingsAlpha);
+ }
+ }
+ if (mPeekable && mAdapter != null && mAdapter.getMode() != Adapter.MODE_OFF) {
+ if (DEBUG) log("panic expand!");
+ mPeekable = false;
+ mModeSpinner.setEnabled(true);
+ mBottom = getExpandedBottom();
+ setExpanded(1);
+ }
+ mInfoWindow.dismiss();
+ }
+ }
+
+ private float getSettingsButtonAlpha() {
+ final boolean full = mAdapter != null && mAdapter.getMode() == Adapter.MODE_FULL;
+ final boolean collapsed = mHintText.getAlpha() == 1;
+ return full || collapsed ? 0 : SETTINGS_ALPHA;
+ }
+
+ private static Path closePath(int size) {
+ final int pad = size / 4;
+ final Path p = new Path();
+ p.moveTo(pad, pad);
+ p.lineTo(size - pad, size - pad);
+ p.moveTo(size - pad, pad);
+ p.lineTo(pad, size - pad);
+ return p;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (DEBUG) log("onMeasure %s %s",
+ MeasureSpec.toString(widthMeasureSpec), MeasureSpec.toString(heightMeasureSpec));
+ if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY) {
+ throw new UnsupportedOperationException("Width must be exact");
+ }
+ if (widthMeasureSpec != mWidthSpec) {
+ if (DEBUG) log(" super.onMeasure");
+ final int hms = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ super.onMeasure(widthMeasureSpec, hms);
+ mBottom = mPeekable ? mHintText.getMeasuredHeight() : getExpandedBottom();
+ mWidthSpec = widthMeasureSpec;
+ }
+ if (DEBUG) log("mBottom (OM) = " + mBottom);
+ setMeasuredDimension(getMeasuredWidth(), mBottom);
+ if (DEBUG) log(" mw=%s mh=%s",
+ toString(getMeasuredWidthAndState()), toString(getMeasuredHeightAndState()));
+ }
+
+ private static String toString(int sizeAndState) {
+ final int size = sizeAndState & MEASURED_SIZE_MASK;
+ final boolean tooSmall = (sizeAndState & MEASURED_STATE_TOO_SMALL) != 0;
+ return size + (tooSmall ? "TOO SMALL" : "");
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ mLayoutRect.set(left, top, right, bottom);
+ if (DEBUG) log("onLayout %s %s %dx%d", changed,
+ mLayoutRect.toShortString(), mLayoutRect.width(), mLayoutRect.height());
+ super.onLayout(changed, left, top, right, bottom);
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ final boolean rt = super.dispatchTouchEvent(ev);
+ if (DEBUG) logTouchEvent("dispatchTouchEvent", rt, ev);
+ return rt;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ final boolean rt = super.onInterceptTouchEvent(ev);
+ if (DEBUG) logTouchEvent("onInterceptTouchEvent", rt, ev);
+ if (ev.getAction() == MotionEvent.ACTION_DOWN
+ && ev.getY() > mCloseButton.getBottom()
+ && mPeekable) {
+ return true;
+ }
+ return rt;
+ }
+
+ private static void logTouchEvent(String method, boolean rt, MotionEvent event) {
+ final String action = MotionEvent.actionToString(event.getAction());
+ Log.d(TAG, method + " " + (rt ? "TRUE" : "FALSE") + " " + action);
+ }
+
+ private int getExpandedBottom() {
+ int b = mModeSpinner.getMeasuredHeight() + mUntilPager.getMeasuredHeight();
+ if (mAlarmWarning.getAlpha() == 1) b += mAlarmWarning.getMeasuredHeight();
+ return b;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean rt = super.onTouchEvent(event);
+ if (DEBUG) logTouchEvent("onTouchEvent", rt, event);
+ if (!mPeekable) {
+ return rt;
+ }
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ mDownY = event.getY();
+ if (DEBUG) log(" mDownY=" + mDownY);
+ mDownBottom = mBottom;
+ return true;
+ } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+ final float dy = event.getY() - mDownY;
+ setPeeked(mDownBottom + (int)dy, getExpandedBottom());
+ } else if (event.getAction() == MotionEvent.ACTION_UP
+ || event.getAction() == MotionEvent.ACTION_CANCEL) {
+ final float dy = event.getY() - mDownY;
+ setPeeked(mDownBottom + (int)dy, getExpandedBottom());
+ if (mPeekable) {
+ close();
+ }
+ }
+ return rt;
+ }
+
+ private void setPeeked(int peeked, int max) {
+ if (DEBUG) log("setPeeked=" + peeked);
+ final int min = mHintText.getBottom();
+ peeked = Math.max(min, Math.min(peeked, max));
+ if (mBottom == peeked) {
+ return;
+ }
+ if (peeked == max) {
+ mPeekable = false;
+ mModeSpinner.setEnabled(true);
+ if (mAdapter != null) {
+ mAdapter.setMode(Adapter.MODE_LIMITED);
+ }
+ }
+ if (peeked == min) {
+ mPeekable = true;
+ mModeSpinner.setEnabled(false);
+ }
+ if (DEBUG) log(" mBottom=" + peeked);
+ mBottom = peeked;
+ final float f = (peeked - min) / (float)(max - min);
+ setExpanded(f);
+ requestLayout();
+ }
+
+ private void setExpanded(float f) {
+ if (DEBUG) log("setExpanded " + f);
+ final int a = (int)(Color.alpha(BACKGROUND) * f);
+ setBackgroundColor(Color.argb(a,
+ Color.red(BACKGROUND), Color.green(BACKGROUND), Color.blue(BACKGROUND)));
+ mHintText.setAlpha(1 - f);
+ mCloseButton.setAlpha(f);
+ mModeSpinner.setAlpha(f);
+ mUntilPager.setAlpha(f);
+ mSettingsButton.setAlpha(f * getSettingsButtonAlpha());
+ }
+
+ private static void log(String msg, Object... args) {
+ Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
+ }
+
+ private static ShapeDrawable sd(Path p, int size, Paint pt) {
+ final ShapeDrawable sd = new ShapeDrawable(new PathShape(p, size, size));
+ sd.getPaint().set(pt);
+ sd.setIntrinsicHeight(size);
+ sd.setIntrinsicWidth(size);
+ return sd;
+ }
+
+ public void dispatchExternalTouchEvent(MotionEvent ev) {
+ onTouchEvent(ev);
+ }
+
+ private static void bounce(final View v, final Runnable midBounce) {
+ v.animate().scaleX(BOUNCE_SCALE).scaleY(BOUNCE_SCALE).setDuration(DURATION / 3)
+ .setListener(new AnimatorListenerAdapter() {
+ private boolean mFired;
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mFired) {
+ mFired = true;
+ if (midBounce != null) {
+ midBounce.run();
+ }
+ v.animate().scaleX(1).scaleY(1).setListener(null).start();
+ }
+ }
+ }).start();
+ }
+
+ private final class UntilPager extends RelativeLayout {
+ private final ImageView mPrev;
+ private final ImageView mNext;
+ private final TextView mText1;
+ private final TextView mText2;
+
+ private TextView mText;
+
+ public UntilPager(Context context, Paint pathPaint, int iconSize) {
+ super(context);
+ mText1 = new TextView(mContext);
+ mText1.setTypeface(CONDENSED);
+ mText1.setTextColor(GRAY);
+ mText1.setGravity(Gravity.CENTER);
+ LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, iconSize);
+ addView(mText1, lp);
+ mText = mText1;
+
+ mText2 = new TextView(mContext);
+ mText2.setTypeface(CONDENSED);
+ mText2.setTextColor(GRAY);
+ mText2.setAlpha(0);
+ mText2.setGravity(Gravity.CENTER);
+ addView(mText2, lp);
+
+ lp = new LayoutParams(iconSize, iconSize);
+ final View v = new View(mContext);
+ v.setBackgroundColor(BACKGROUND);
+ addView(v, lp);
+ mPrev = new ImageView(mContext);
+ mPrev.setId(android.R.id.button1);
+ mPrev.setImageDrawable(sd(prevPath(iconSize), iconSize, pathPaint));
+ addView(mPrev, lp);
+ mPrev.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onNav(v, -1);
+ }
+ });
+
+ lp = new LayoutParams(iconSize, iconSize);
+ lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ final View v2 = new View(mContext);
+ v2.setBackgroundColor(BACKGROUND);
+ addView(v2, lp);
+ mNext = new ImageView(mContext);
+ mNext.setId(android.R.id.button2);
+ mNext.setImageDrawable(sd(nextPath(iconSize), iconSize, pathPaint));
+ addView(mNext, lp);
+ mNext.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onNav(v, 1);
+ }
+ });
+
+ updateState();
+ }
+
+ private void onNav(View v, int d) {
+ bounce(v, null);
+ if (mAdapter == null) {
+ return;
+ }
+ if (mAdapter.getExitConditionCount() == 1) {
+ horBounce(d);
+ return;
+ }
+ final int w = getWidth();
+ final float s = Math.signum(d);
+ final TextView current = mText;
+ final TextView other = mText == mText1 ? mText2 : mText1;
+ final ExitCondition ec = mAdapter.getExitCondition(d);
+ setText(other, ec);
+ other.setTranslationX(-s * w);
+ other.animate().translationX(0).alpha(1).setDuration(DURATION).start();
+ current.animate().translationX(s * w).alpha(0).setDuration(DURATION).start();
+ mText = other;
+ mAdapter.select(ec);
+ }
+
+ private void horBounce(int d) {
+ final int w = getWidth();
+ mText.animate()
+ .setDuration(BOUNCE_DURATION)
+ .translationX(Math.signum(d) * w / 20)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mText.animate().translationX(0).setListener(null).start();
+ }
+ }).start();
+ }
+
+ private void setText(final TextView textView, final ExitCondition ec) {
+ SpannableStringBuilder ss = new SpannableStringBuilder(ec.line1 + "\n" + ec.line2);
+ ss.setSpan(new RelativeSizeSpan(1.5f), (ec.line1 + "\n").length(), ss.length(),
+ Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
+ if (ec.action != null) {
+ ss.setSpan(new CustomLinkSpan() {
+ @Override
+ public void onClick() {
+ // TODO wire up links
+ Toast.makeText(mContext, ec.action, Toast.LENGTH_SHORT).show();
+ }
+ }, (ec.line1 + "\n").length(), ss.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
+ textView.setMovementMethod(LinkMovementMethod.getInstance());
+ } else {
+ textView.setMovementMethod(null);
+ }
+ textView.setText(ss);
+ }
+
+ private void updateState() {
+ if (mAdapter == null) {
+ return;
+ }
+ setText(mText, mAdapter.getExitCondition(0));
+ }
+
+ private Path prevPath(int size) {
+ final int hp = size / 3;
+ final int vp = size / 4;
+ final Path p = new Path();
+ p.moveTo(size - hp, vp);
+ p.lineTo(hp, size / 2);
+ p.lineTo(size - hp, size - vp);
+ return p;
+ }
+
+ private Path nextPath(int size) {
+ final int hp = size / 3;
+ final int vp = size / 4;
+ Path p = new Path();
+ p.moveTo(hp, vp);
+ p.lineTo(size - hp, size / 2);
+ p.lineTo(hp, size - vp);
+ return p;
+ }
+ }
+
+ private abstract static class CustomLinkSpan extends URLSpan {
+ abstract public void onClick();
+
+ public CustomLinkSpan() {
+ super("#");
+ }
+
+ @Override
+ public void updateDrawState(TextPaint ds) {
+ super.updateDrawState(ds);
+ ds.setUnderlineText(false);
+ ds.bgColor = BACKGROUND;
+ }
+
+ @Override
+ public void onClick(View widget) {
+ onClick();
+ }
+ }
+
+ public interface Adapter {
+ public static final int MODE_OFF = 0;
+ public static final int MODE_LIMITED = 1;
+ public static final int MODE_FULL = 2;
+
+ int getMode();
+ void setMode(int mode);
+ void select(ExitCondition ec);
+ void cancel();
+ void setCallbacks(Callbacks callbacks);
+ ExitCondition getExitCondition(int d);
+ int getExitConditionCount();
+
+ public static class ExitCondition {
+ public String summary;
+ public String line1;
+ public String line2;
+ public String action;
+ }
+
+ public interface Callbacks {
+ void onChanged();
+ }
+ }
+
+ private final class ModeSpinner extends Spinner {
+ public ModeSpinner(final Context context) {
+ super(context);
+ setBackgroundResource(R.drawable.spinner_default_holo_dark_am_no_underline);
+ final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(mContext, 0) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (DEBUG) log("getView %s parent=%s", position, parent);
+ return getDropDownView(position, convertView, parent);
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ if (DEBUG) log("getDropDownView %s cv=%s parent=%s",
+ position, convertView, parent);
+ final TextView tv = convertView != null ? (TextView) convertView
+ : new TextView(context);
+ final int mode = getItem(position);
+ tv.setText(modeToString(mode));
+ if (convertView == null) {
+ if (DEBUG) log(" setting up view");
+ tv.setTextColor(GRAY);
+ tv.setTypeface(CONDENSED);
+ tv.setAllCaps(true);
+ tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, tv.getTextSize() * 1.5f);
+ final int p = (int) tv.getTextSize() / 2;
+ if (parent instanceof ListView) {
+ tv.setPadding(p, p, p, p);
+ } else {
+ tv.setGravity(Gravity.CENTER_HORIZONTAL);
+ tv.setPadding(p, 0, p, 0);
+ }
+ }
+ tv.setOnTouchListener(new OnTouchListener(){
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (DEBUG) log("onTouch %s %s", tv.getText(),
+ MotionEvent.actionToString(event.getAction()));
+ if (mAdapter != null) {
+ mAdapter.setMode(mode);
+ }
+ return false;
+ }
+
+ });
+ return tv;
+ }
+ };
+ adapter.add(Adapter.MODE_LIMITED);
+ adapter.add(Adapter.MODE_FULL);
+ setAdapter(adapter);
+ }
+
+ public void updateState() {
+ int mode = mAdapter != null ? mAdapter.getMode() : Adapter.MODE_LIMITED;
+ if (mode == Adapter.MODE_OFF) {
+ mode = Adapter.MODE_LIMITED;
+ }
+ if (DEBUG) log("setSelectedMode " + mode);
+ for (int i = 0; i < getAdapter().getCount(); i++) {
+ if (getAdapter().getItem(i).equals(mode)) {
+ if (DEBUG) log(" setting selection = " + i);
+ setSelection(i, true);
+ return;
+ }
+ }
+ }
+
+ private String modeToString(int mode) {
+ if (mode == Adapter.MODE_LIMITED) return "Limited interruptions";
+ if (mode == Adapter.MODE_FULL) return "Zero interruptions";
+ throw new UnsupportedOperationException("Unsupported mode: " + mode);
+ }
+ }
+
+ private final class AlarmWarning extends LinearLayout {
+ public AlarmWarning(Context context) {
+ super(context);
+ setOrientation(HORIZONTAL);
+
+ final TextView tv = new TextView(mContext);
+ tv.setTextColor(GRAY);
+ tv.setGravity(Gravity.TOP);
+ tv.setTypeface(CONDENSED);
+ tv.setText(FULL_TEXT);
+ addView(tv);
+
+ final ImageView icon = new ImageView(mContext);
+ icon.setAlpha(.75f);
+ int size = (int)tv.getTextSize();
+ icon.setImageResource(android.R.drawable.ic_dialog_alert);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size);
+ final int p = size / 4;
+ lp.bottomMargin = lp.topMargin = lp.rightMargin = lp.leftMargin = p;
+ addView(icon, 0, lp);
+ setPadding(p, 0, p, p);
+ }
+
+ public void updateState(boolean animate) {
+ final boolean visible = mAdapter != null && mAdapter.getMode() == Adapter.MODE_FULL;
+ final float alpha = visible ? 1 : 0;
+ if (alpha == getAlpha()) {
+ return;
+ }
+ if (animate) {
+ final boolean in = alpha == 1;
+ animate().alpha(alpha).setUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (mPeekable || mClosing) {
+ return;
+ }
+ float f = animation.getAnimatedFraction();
+ if (!in) {
+ f = 1 - f;
+ }
+ ZenModeView.this.mBottom = mUntilPager.getBottom()
+ + (int)(mAlarmWarning.getMeasuredHeight() * f);
+ if (DEBUG) log("mBottom (AW) = " + mBottom);
+ requestLayout();
+ }
+ }).start();
+ } else {
+ setAlpha(alpha);
+ requestLayout();
+ }
+ }
+ }
+
+ private static class InfoWindow extends PopupWindow implements Runnable {
+ private final TextView mText;
+
+ public InfoWindow(Context context, String text) {
+ mText = new TextView(context);
+ mText.setTypeface(CONDENSED);
+ mText.setBackgroundColor(0xbb000000);
+ mText.setTextColor(0xffffffff);
+ mText.setText(text);
+ mText.setGravity(Gravity.CENTER);
+ setAnimationStyle(android.R.style.Animation_Toast);
+ setContentView(mText);
+ }
+
+ @Override
+ public void run() {
+ dismiss();
+ }
+
+ public void show(View over) {
+ setWidth(over.getMeasuredWidth());
+ setHeight(over.getMeasuredHeight());
+ final int[] loc = new int[2];
+ over.getLocationInWindow(loc);
+ showAtLocation(over, Gravity.NO_GRAVITY, loc[0], loc[1]);
+ over.postDelayed(this, INFO_WINDOW_DELAY);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
new file mode 100644
index 0000000..2078b3c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2014 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.systemui.statusbar.phone;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ZenModeViewAdapter implements ZenModeView.Adapter {
+ private static final String TAG = "ZenModeViewAdapter";
+
+ private final Context mContext;
+ private final ContentResolver mResolver;
+ private final Handler mHandler = new Handler();
+ private final List<ExitCondition> mExits = Arrays.asList(
+ newExit("Until you delete this", "Until", "You delete this"));
+
+ private Callbacks mCallbacks;
+ private int mExitIndex;
+
+ public ZenModeViewAdapter(Context context) {
+ mContext = context;
+ mResolver = mContext.getContentResolver();
+ mResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
+ false, new SettingsObserver(mHandler));
+ }
+
+ @Override
+ public int getMode() {
+ final int v = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+ if (v == Settings.Global.ZEN_MODE_LIMITED) return MODE_LIMITED;
+ if (v == Settings.Global.ZEN_MODE_FULL) return MODE_FULL;
+ return MODE_OFF;
+ }
+
+ @Override
+ public void setMode(int mode) {
+ final int v = mode == MODE_LIMITED ? Settings.Global.ZEN_MODE_LIMITED
+ : mode == MODE_FULL ? Settings.Global.ZEN_MODE_FULL
+ : Settings.Global.ZEN_MODE_OFF;
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE, v);
+ }
+ });
+ }
+
+ @Override
+ public void cancel() {
+ if (mExitIndex != 0) {
+ mExitIndex = 0;
+ mHandler.post(mChange);
+ }
+ setMode(MODE_OFF);
+ }
+
+ @Override
+ public void setCallbacks(final Callbacks callbacks) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallbacks = callbacks;
+ }
+ });
+ }
+
+ @Override
+ public ExitCondition getExitCondition(int d) {
+ final int n = mExits.size();
+ final int i = (n + (mExitIndex + (int)Math.signum(d))) % n;
+ return mExits.get(i);
+ }
+
+ @Override
+ public int getExitConditionCount() {
+ return mExits.size();
+ }
+
+ @Override
+ public void select(ExitCondition ec) {
+ final int i = mExits.indexOf(ec);
+ if (i == -1 || i == mExitIndex) {
+ return;
+ }
+ mExitIndex = i;
+ mHandler.post(mChange);
+ }
+
+ private static ExitCondition newExit(String summary, String line1, String line2) {
+ final ExitCondition rt = new ExitCondition();
+ rt.summary = summary;
+ rt.line1 = line1;
+ rt.line2 = line2;
+ return rt;
+ }
+
+ private final Runnable mChange = new Runnable() {
+ public void run() {
+ if (mCallbacks == null) {
+ return;
+ }
+ try {
+ mCallbacks.onChanged();
+ } catch (Throwable t) {
+ Log.w(TAG, "Error dispatching onChanged to " + mCallbacks, t);
+ }
+ }
+ };
+
+ private final class SettingsObserver extends ContentObserver {
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ mChange.run(); // already on handler
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index df2aaca..243bd74 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -16,6 +16,8 @@
package com.android.server.notification;
+import android.os.IBinder;
+
public interface NotificationDelegate {
void onSetDisabled(int status);
void onClearAll();
@@ -24,4 +26,5 @@ public interface NotificationDelegate {
void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message);
void onPanelRevealed();
+ boolean allowDisable(int what, IBinder token, String pkg);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ab46dfe..b791435 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -154,7 +154,7 @@ public class NotificationManagerService extends SystemService {
private long[] mFallbackVibrationPattern;
boolean mSystemReady;
- int mDisabledNotifications;
+ private boolean mDisableNotificationAlerts;
NotificationRecord mSoundNotification;
NotificationRecord mVibrateNotification;
@@ -202,6 +202,19 @@ public class NotificationManagerService extends SystemService {
final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>();
+ private int mZenMode;
+ private int mPreZenAlarmVolume = -1;
+ private int mPreZenRingerMode = -1;
+ // temporary, until we update apps to provide metadata
+ private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
+ "com.google.android.dialer",
+ "com.android.phone"
+ ));
+ private static final Set<String> ALARM_PACKAGES = new HashSet<String>(Arrays.asList(
+ "com.google.android.deskclock"
+ ));
+ private static final String EXTRA_INTERCEPT = "android.intercept";
+
private class NotificationListenerInfo implements IBinder.DeathRecipient {
INotificationListener listener;
ComponentName component;
@@ -869,8 +882,8 @@ public class NotificationManagerService extends SystemService {
@Override
public void onSetDisabled(int status) {
synchronized (mNotificationList) {
- mDisabledNotifications = status;
- if ((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
+ mDisableNotificationAlerts = (status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
+ if (mDisableNotificationAlerts) {
// cancel whatever's going on
long identity = Binder.clearCallingIdentity();
try {
@@ -968,6 +981,14 @@ public class NotificationManagerService extends SystemService {
}
Binder.restoreCallingIdentity(ident);
}
+
+ @Override
+ public boolean allowDisable(int what, IBinder token, String pkg) {
+ if (mZenMode == Settings.Global.ZEN_MODE_FULL && isCall(pkg, null)) {
+ return false;
+ }
+ return true;
+ }
};
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -1077,6 +1098,12 @@ public class NotificationManagerService extends SystemService {
private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
= Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+ private final Uri ZEN_MODE
+ = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
+
+ private final Uri MODE_RINGER
+ = Settings.Global.getUriFor(Settings.Global.MODE_RINGER);
+
SettingsObserver(Handler handler) {
super(handler);
}
@@ -1087,6 +1114,10 @@ public class NotificationManagerService extends SystemService {
false, this, UserHandle.USER_ALL);
resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(ZEN_MODE,
+ false, this);
+ resolver.registerContentObserver(MODE_RINGER,
+ false, this);
update(null);
}
@@ -1107,6 +1138,12 @@ public class NotificationManagerService extends SystemService {
if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) {
rebindListenerServices();
}
+ if (ZEN_MODE.equals(uri)) {
+ updateZenMode();
+ }
+ if (MODE_RINGER.equals(uri)) {
+ updateRingerMode();
+ }
}
}
@@ -1170,8 +1207,10 @@ public class NotificationManagerService extends SystemService {
// flag at least once and we'll go back to 0 after that.
if (0 == Settings.Global.getInt(getContext().getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0)) {
- mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
+ mDisableNotificationAlerts = true;
}
+ updateRingerMode();
+ updateZenMode();
// register for various Intents
IntentFilter filter = new IntentFilter();
@@ -1622,8 +1661,10 @@ public class NotificationManagerService extends SystemService {
pw.println(" mSoundNotification=" + mSoundNotification);
pw.println(" mVibrateNotification=" + mVibrateNotification);
- pw.println(" mDisabledNotifications=0x"
- + Integer.toHexString(mDisabledNotifications));
+ pw.println(" mDisableNotificationAlerts=" + mDisableNotificationAlerts);
+ pw.println(" mZenMode=" + Settings.Global.zenModeToString(mZenMode));
+ pw.println(" mPreZenAlarmVolume=" + mPreZenAlarmVolume);
+ pw.println(" mPreZenRingerMode=" + mPreZenRingerMode);
pw.println(" mSystemReady=" + mSystemReady);
pw.println(" mArchive=" + mArchive.toString());
Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
@@ -1767,9 +1808,13 @@ public class NotificationManagerService extends SystemService {
return;
}
- // Should this notification make noise, vibe, or use the LED?
- final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD);
+ // Is this notification intercepted by zen mode?
+ final boolean intercept = shouldIntercept(pkg, notification);
+ notification.extras.putBoolean(EXTRA_INTERCEPT, intercept);
+ // Should this notification make noise, vibe, or use the LED?
+ final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) && !intercept;
+ if (DBG) Slog.v(TAG, "canInterrupt=" + canInterrupt + " intercept=" + intercept);
synchronized (mNotificationList) {
final StatusBarNotification n = new StatusBarNotification(
pkg, id, tag, callingUid, callingPid, score, notification, user);
@@ -1851,8 +1896,7 @@ public class NotificationManagerService extends SystemService {
}
// If we're not supposed to beep, vibrate, etc. then don't.
- if (((mDisabledNotifications
- & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)
+ if (!mDisableNotificationAlerts
&& (!(old != null
&& (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
&& (r.getUserId() == UserHandle.USER_ALL ||
@@ -1860,7 +1904,7 @@ public class NotificationManagerService extends SystemService {
&& canInterrupt
&& mSystemReady
&& mAudioManager != null) {
-
+ if (DBG) Slog.v(TAG, "Interrupting!");
// sound
// should we use the default notification sound? (indicated either by
@@ -1905,6 +1949,8 @@ public class NotificationManagerService extends SystemService {
final IRingtonePlayer player =
mAudioManager.getRingtonePlayer();
if (player != null) {
+ if (DBG) Slog.v(TAG, "Playing sound " + soundUri
+ + " on stream " + audioStreamType);
player.playAsync(soundUri, user, looping, audioStreamType);
}
} catch (RemoteException e) {
@@ -2437,4 +2483,67 @@ public class NotificationManagerService extends SystemService {
updateLightsLocked();
}
}
+
+ private void updateRingerMode() {
+ final int ringerMode = Settings.Global.getInt(getContext().getContentResolver(),
+ Settings.Global.MODE_RINGER, -1);
+ final boolean nonSilentRingerMode = ringerMode == AudioManager.RINGER_MODE_NORMAL
+ || ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+ if (mZenMode == Settings.Global.ZEN_MODE_FULL && nonSilentRingerMode) {
+ Settings.Global.putInt(getContext().getContentResolver(),
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+ }
+ }
+
+ private void updateZenMode() {
+ mZenMode = Settings.Global.getInt(getContext().getContentResolver(),
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+ if (DBG) Slog.d(TAG, "updateZenMode " + Settings.Global.zenModeToString(mZenMode));
+ if (mAudioManager != null) {
+ if (mZenMode == Settings.Global.ZEN_MODE_FULL) {
+ // calls vibrate if ringer mode = vibrate, so set the ringer mode as well
+ mPreZenRingerMode = mAudioManager.getRingerMode();
+ if (DBG) Slog.d(TAG, "Muting calls mPreZenRingerMode=" + mPreZenRingerMode);
+ mAudioManager.setStreamMute(AudioManager.STREAM_RING, true);
+ mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+ // alarms don't simply respect mute, so set the volume as well
+ mPreZenAlarmVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+ if (DBG) Slog.d(TAG, "Muting alarms mPreZenAlarmVolume=" + mPreZenAlarmVolume);
+ mAudioManager.setStreamMute(AudioManager.STREAM_ALARM, true);
+ mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, 0, 0);
+ } else {
+ if (DBG) Slog.d(TAG, "Unmuting calls");
+ mAudioManager.setStreamMute(AudioManager.STREAM_RING, false);
+ if (mPreZenRingerMode != -1) {
+ if (DBG) Slog.d(TAG, "Restoring ringer mode to " + mPreZenRingerMode);
+ mAudioManager.setRingerMode(mPreZenRingerMode);
+ mPreZenRingerMode = -1;
+ }
+ if (DBG) Slog.d(TAG, "Unmuting alarms");
+ mAudioManager.setStreamMute(AudioManager.STREAM_ALARM, false);
+ if (mPreZenAlarmVolume != -1) {
+ if (DBG) Slog.d(TAG, "Restoring STREAM_ALARM to " + mPreZenAlarmVolume);
+ mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mPreZenAlarmVolume, 0);
+ mPreZenAlarmVolume = -1;
+ }
+ }
+ }
+ }
+
+ private boolean isCall(String pkg, Notification n) {
+ return CALL_PACKAGES.contains(pkg);
+ }
+
+ private boolean isAlarm(String pkg, Notification n) {
+ return ALARM_PACKAGES.contains(pkg);
+ }
+
+ private boolean shouldIntercept(String pkg, Notification n) {
+ if (mZenMode == Settings.Global.ZEN_MODE_LIMITED) {
+ return !isCall(pkg, n) && !isAlarm(pkg, n);
+ } else if (mZenMode == Settings.Global.ZEN_MODE_FULL) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 2ae467e..8219eb5 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -23,9 +23,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.util.Slog;
@@ -207,6 +205,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub
@Override
public void disable(int what, IBinder token, String pkg) {
+ if (!mNotificationDelegate.allowDisable(what, token, pkg)) {
+ if (SPEW) Slog.d(TAG, "Blocking disable request from " + pkg);
+ return;
+ }
disableInternal(mCurrentUserId, what, token, pkg);
}
@@ -676,26 +678,4 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
}
-
- private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
- || Intent.ACTION_SCREEN_OFF.equals(action)) {
- collapsePanels();
- }
- /*
- else if (Telephony.Intents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
- updateNetworkName(intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_SPN, false),
- intent.getStringExtra(Telephony.Intents.EXTRA_SPN),
- intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_PLMN, false),
- intent.getStringExtra(Telephony.Intents.EXTRA_PLMN));
- }
- else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
- updateResources();
- }
- */
- }
- };
-
}