diff options
Diffstat (limited to 'services')
17 files changed, 429 insertions, 283 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5527528..d7a19ad 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -514,6 +514,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { // sequence number of NetworkRequests private int mNextNetworkRequestId = 1; + private static final int UID_UNUSED = -1; + public ConnectivityService(Context context, INetworkManagementService netd, INetworkStatsService statsService, INetworkPolicyManager policyManager) { // Currently, omitting a NetworkFactory will create one internally @@ -1673,10 +1675,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { } return false; } + final int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { LinkProperties lp = tracker.getLinkProperties(); - boolean ok = addRouteToAddress(lp, addr, exempt, tracker.getNetwork().netId); + boolean ok = modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt, + tracker.getNetwork().netId, uid); if (DBG) log("requestRouteToHostAddress ok=" + ok); return ok; } finally { @@ -1686,24 +1690,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable, boolean exempt, int netId) { - return modifyRoute(p, r, 0, ADD, toDefaultTable, exempt, netId); + return modifyRoute(p, r, 0, ADD, toDefaultTable, exempt, netId, false, UID_UNUSED); } private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable, int netId) { - return modifyRoute(p, r, 0, REMOVE, toDefaultTable, UNEXEMPT, netId); - } - - private boolean addRouteToAddress(LinkProperties lp, InetAddress addr, boolean exempt, - int netId) { - return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt, netId); - } - - private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr, int netId) { - return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE, UNEXEMPT, netId); + return modifyRoute(p, r, 0, REMOVE, toDefaultTable, UNEXEMPT, netId, false, UID_UNUSED); } private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd, - boolean toDefaultTable, boolean exempt, int netId) { + boolean toDefaultTable, boolean exempt, int netId, int uid) { RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr); if (bestRoute == null) { bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName()); @@ -1718,11 +1713,18 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface); } } - return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable, exempt, netId); + return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable, exempt, netId, true, uid); } + /* + * TODO: Clean all this stuff up. Once we have UID-based routing, stuff will break due to + * incorrect tracking of mAddedRoutes, so a cleanup becomes necessary and urgent. But at + * the same time, there'll be no more need to track mAddedRoutes or mExemptAddresses, + * or even have the concept of an exempt address, or do things like "selectBestRoute", or + * determine "default" vs "secondary" table, etc., so the cleanup becomes possible. + */ private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd, - boolean toDefaultTable, boolean exempt, int netId) { + boolean toDefaultTable, boolean exempt, int netId, boolean legacy, int uid) { if ((lp == null) || (r == null)) { if (DBG) log("modifyRoute got unexpected null: " + lp + ", " + r); return false; @@ -1751,7 +1753,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute.getGateway(), ifaceName); } - modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable, exempt, netId); + modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable, exempt, netId, + legacy, uid); } } if (doAdd) { @@ -1761,7 +1764,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { synchronized (mRoutesLock) { // only track default table - only one apps can effect mAddedRoutes.add(r); - mNetd.addRoute(netId, r); + if (legacy) { + mNetd.addLegacyRouteForNetId(netId, r, uid); + } else { + mNetd.addRoute(netId, r); + } if (exempt) { LinkAddress dest = r.getDestination(); if (!mExemptAddresses.contains(dest)) { @@ -1771,7 +1778,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } } else { - mNetd.addRoute(netId, r); + if (legacy) { + mNetd.addLegacyRouteForNetId(netId, r, uid); + } else { + mNetd.addRoute(netId, r); + } } } catch (Exception e) { // never crash - catch them all @@ -1787,7 +1798,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (mAddedRoutes.contains(r) == false) { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { - mNetd.removeRoute(netId, r); + if (legacy) { + mNetd.removeLegacyRouteForNetId(netId, r, uid); + } else { + mNetd.removeRoute(netId, r); + } LinkAddress dest = r.getDestination(); if (mExemptAddresses.contains(dest)) { mNetd.clearHostExemption(dest); @@ -1805,7 +1820,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { - mNetd.removeRoute(netId, r); + if (legacy) { + mNetd.removeLegacyRouteForNetId(netId, r, uid); + } else { + mNetd.removeRoute(netId, r); + } } catch (Exception e) { // never crash - catch them all if (VDBG) loge("Exception trying to remove a route: " + e); diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index d5f045e..d31fb60 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2372,6 +2372,18 @@ class MountService extends IMountService.Stub } } + voldPath = maybeTranslatePathForVold(appPath, + userEnv.buildExternalStorageAppMediaDirs(callingPkg), + userEnv.buildExternalStorageAppMediaDirsForVold(callingPkg)); + if (voldPath != null) { + try { + mConnector.execute("volume", "mkdirs", voldPath); + return 0; + } catch (NativeDaemonConnectorException e) { + return e.getCode(); + } + } + throw new SecurityException("Invalid mkdirs path: " + appPath); } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 137387e..eefe8da 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -885,7 +885,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub final LinkAddress la = route.getDestination(); cmd.appendArg(route.getInterface()); cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getNetworkPrefixLength()); - cmd.appendArg(route.getGateway().getHostAddress()); + if (route.hasGateway()) { + cmd.appendArg(route.getGateway().getHostAddress()); + } try { mConnector.execute(cmd); @@ -1993,14 +1995,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub private void modifyLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid, String action) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - final Command cmd = new Command("network", "legacy", uid, "route", action, netId); + final Command cmd = new Command("network", "route", "legacy", uid, action, netId); - // create quadlet: dest-ip-addr prefixlength gateway-ip-addr iface + // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr final LinkAddress la = routeInfo.getDestination(); - cmd.appendArg(la.getAddress().getHostAddress()); - cmd.appendArg(la.getNetworkPrefixLength()); - cmd.appendArg(routeInfo.getGateway().getHostAddress()); cmd.appendArg(routeInfo.getInterface()); + cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getNetworkPrefixLength()); + if (routeInfo.hasGateway()) { + cmd.appendArg(routeInfo.getGateway().getHostAddress()); + } try { mConnector.execute(cmd); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 033b967..108a079 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -247,7 +247,8 @@ public final class ActiveServices { maxBg = Integer.parseInt(SystemProperties.get("ro.config.max_starting_bg", "0")); } catch(RuntimeException e) { } - mMaxStartingBackground = maxBg > 0 ? maxBg : ActivityManager.isLowRamDeviceStatic() ? 1 : 3; + mMaxStartingBackground = maxBg > 0 + ? maxBg : ActivityManager.isLowRamDeviceStatic() ? 1 : 8; } ServiceRecord getServiceByName(ComponentName name, int callingUser) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 0b1c2b8..0cc53d1 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -204,6 +204,10 @@ public final class ActivityStackSupervisor implements DisplayListener { /** Set when we have taken too long waiting to go to sleep. */ boolean mSleepTimeout = false; + /** Indicates if we are running on a Leanback-only (TV) device. Only initialized after + * setWindowManager is called. **/ + private boolean mLeanbackOnlyDevice; + /** * We don't want to allow the device to go to sleep while in the process * of launching an activity. This is primarily to allow alarm intent @@ -268,6 +272,9 @@ public final class ActivityStackSupervisor implements DisplayListener { mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); + + // Initialize this here, now that we can get a valid reference to PackageManager. + mLeanbackOnlyDevice = isLeanbackOnlyDevice(); } } @@ -1375,7 +1382,10 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityStack adjustStackFocus(ActivityRecord r, boolean newTask) { final TaskRecord task = r.task; - if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) { + + // On leanback only devices we should keep all activities in the same stack. + if (!mLeanbackOnlyDevice && + (r.isApplicationActivity() || (task != null && task.isApplicationTask()))) { if (task != null) { final ActivityStack taskStack = task.stack; if (taskStack.isOnHomeDisplay()) { @@ -3423,4 +3433,16 @@ public final class ActivityStackSupervisor implements DisplayListener { return "VirtualActivityDisplay={" + mDisplayId + "}"; } } + + private boolean isLeanbackOnlyDevice() { + boolean onLeanbackOnly = false; + try { + onLeanbackOnly = AppGlobals.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_LEANBACK_ONLY); + } catch (RemoteException e) { + // noop + } + + return onLeanbackOnly; + } } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 030e3ed..c909a54 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -66,13 +66,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { * These are the playback states that count as currently active. */ private static final int[] ACTIVE_STATES = { - PlaybackState.PLAYSTATE_FAST_FORWARDING, - PlaybackState.PLAYSTATE_REWINDING, - PlaybackState.PLAYSTATE_SKIPPING_BACKWARDS, - PlaybackState.PLAYSTATE_SKIPPING_FORWARDS, - PlaybackState.PLAYSTATE_BUFFERING, - PlaybackState.PLAYSTATE_CONNECTING, - PlaybackState.PLAYSTATE_PLAYING }; + PlaybackState.STATE_FAST_FORWARDING, + PlaybackState.STATE_REWINDING, + PlaybackState.STATE_SKIPPING_TO_PREVIOUS, + PlaybackState.STATE_SKIPPING_TO_NEXT, + PlaybackState.STATE_BUFFERING, + PlaybackState.STATE_CONNECTING, + PlaybackState.STATE_PLAYING }; /** * The length of time a session will still be considered active after @@ -301,7 +301,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { if (isActiveState(state)) { return true; } - if (state == mPlaybackState.PLAYSTATE_PAUSED) { + if (state == mPlaybackState.STATE_PAUSED) { long inactiveTime = SystemClock.uptimeMillis() - mLastActiveTime; if (inactiveTime < ACTIVE_BUFFER) { return true; @@ -509,12 +509,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } PlaybackState result = null; if (state != null) { - if (state.getState() == PlaybackState.PLAYSTATE_PLAYING - || state.getState() == PlaybackState.PLAYSTATE_FAST_FORWARDING - || state.getState() == PlaybackState.PLAYSTATE_REWINDING) { + if (state.getState() == PlaybackState.STATE_PLAYING + || state.getState() == PlaybackState.STATE_FAST_FORWARDING + || state.getState() == PlaybackState.STATE_REWINDING) { long updateTime = state.getLastPositionUpdateTime(); if (updateTime > 0) { - long position = (long) (state.getRate() + long position = (long) (state.getPlaybackRate() * (SystemClock.elapsedRealtime() - updateTime)) + state.getPosition(); if (duration >= 0 && position > duration) { position = duration; @@ -522,7 +522,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { position = 0; } result = new PlaybackState(state); - result.setState(state.getState(), position, state.getRate()); + result.setState(state.getState(), position, state.getPlaybackRate()); } } } @@ -588,7 +588,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { public void setPlaybackState(PlaybackState state) { int oldState = mPlaybackState == null ? 0 : mPlaybackState.getState(); int newState = state == null ? 0 : state.getState(); - if (isActiveState(oldState) && newState == PlaybackState.PLAYSTATE_PAUSED) { + if (isActiveState(oldState) && newState == PlaybackState.STATE_PAUSED) { mLastActiveTime = SystemClock.elapsedRealtime(); } mPlaybackState = state; @@ -649,14 +649,16 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { mCb = cb; } - public void sendMediaButton(KeyEvent keyEvent, int sequenceId, ResultReceiver cb) { + public boolean sendMediaButton(KeyEvent keyEvent, int sequenceId, ResultReceiver cb) { Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); try { mCb.onMediaButton(mediaButtonIntent, sequenceId, cb); + return true; } catch (RemoteException e) { Slog.e(TAG, "Remote failure in sendMediaRequest.", e); } + return false; } public void sendCommand(String command, Bundle extras, ResultReceiver cb) { @@ -788,8 +790,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void sendMediaButton(KeyEvent mediaButtonIntent) { - mSessionCb.sendMediaButton(mediaButtonIntent, 0, null); + public boolean sendMediaButton(KeyEvent mediaButtonIntent) { + return mSessionCb.sendMediaButton(mediaButtonIntent, 0, null); } @Override diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index 7ba9212..56236f8 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -33,18 +33,18 @@ public class MediaSessionStack { * bump priority regardless of the old state. */ private static final int[] ALWAYS_PRIORITY_STATES = { - PlaybackState.PLAYSTATE_FAST_FORWARDING, - PlaybackState.PLAYSTATE_REWINDING, - PlaybackState.PLAYSTATE_SKIPPING_BACKWARDS, - PlaybackState.PLAYSTATE_SKIPPING_FORWARDS }; + PlaybackState.STATE_FAST_FORWARDING, + PlaybackState.STATE_REWINDING, + PlaybackState.STATE_SKIPPING_TO_PREVIOUS, + PlaybackState.STATE_SKIPPING_TO_NEXT }; /** * These are states that usually indicate the user took an action if they * were entered from a non-priority state. */ private static final int[] TRANSITION_PRIORITY_STATES = { - PlaybackState.PLAYSTATE_BUFFERING, - PlaybackState.PLAYSTATE_CONNECTING, - PlaybackState.PLAYSTATE_PLAYING }; + PlaybackState.STATE_BUFFERING, + PlaybackState.STATE_CONNECTING, + PlaybackState.STATE_PLAYING }; private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>(); diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java index 49293d3..b30baea 100644 --- a/services/core/java/com/android/server/notification/NotificationComparator.java +++ b/services/core/java/com/android/server/notification/NotificationComparator.java @@ -21,11 +21,10 @@ import java.util.Comparator; * Sorts notificaitons into attention-relelvant order. */ public class NotificationComparator - implements Comparator<NotificationManagerService.NotificationRecord> { + implements Comparator<NotificationRecord> { @Override - public int compare(NotificationManagerService.NotificationRecord lhs, - NotificationManagerService.NotificationRecord rhs) { + public int compare(NotificationRecord lhs, NotificationRecord rhs) { if (lhs.isRecentlyIntrusive() != rhs.isRecentlyIntrusive()) { return lhs.isRecentlyIntrusive() ? -1 : 1; } diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java index db17f3a..d8ab9d7 100644 --- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java @@ -20,8 +20,6 @@ import android.app.Notification; import android.content.Context; import android.util.Slog; -import com.android.server.notification.NotificationManagerService.NotificationRecord; - /** * This {@link com.android.server.notification.NotificationSignalExtractor} noticies noisy * notifications and marks them to get a temporary ranking bump. diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index bbc3091..cb78a45 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -43,7 +43,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; import android.content.res.Resources; import android.database.ContentObserver; -import android.graphics.Bitmap; import android.media.AudioManager; import android.media.IRingtonePlayer; import android.net.Uri; @@ -60,13 +59,13 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.Vibrator; import android.provider.Settings; -import android.service.notification.INotificationListener; +import android.service.notification.Condition; import android.service.notification.IConditionListener; import android.service.notification.IConditionProvider; +import android.service.notification.INotificationListener; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationRankingUpdate; import android.service.notification.StatusBarNotification; -import android.service.notification.Condition; import android.service.notification.ZenModeConfig; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -87,7 +86,6 @@ import com.android.server.lights.Light; import com.android.server.lights.LightsManager; import com.android.server.notification.ManagedServices.ManagedServiceInfo; import com.android.server.notification.ManagedServices.UserProfiles; -import com.android.server.notification.NotificationUsageStats.SingleNotificationStats; import com.android.server.statusbar.StatusBarManagerInternal; import libcore.io.IoUtils; @@ -103,10 +101,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.lang.reflect.Array; import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -211,8 +207,6 @@ public class NotificationManagerService extends SystemService { private ConditionProviders mConditionProviders; private NotificationUsageStats mUsageStats; - private static final String EXTRA_INTERCEPT = "android.intercept"; - private static final int MY_UID = Process.myUid(); private static final int MY_PID = Process.myPid(); private static final int REASON_DELEGATE_CLICK = 1; @@ -425,144 +419,6 @@ public class NotificationManagerService extends SystemService { return true; } - private static String idDebugString(Context baseContext, String packageName, int id) { - Context c = null; - - if (packageName != null) { - try { - c = baseContext.createPackageContext(packageName, 0); - } catch (NameNotFoundException e) { - c = baseContext; - } - } else { - c = baseContext; - } - - String pkg; - String type; - String name; - - Resources r = c.getResources(); - try { - return r.getResourceName(id); - } catch (Resources.NotFoundException e) { - return "<name unknown>"; - } - } - - - - public static final class NotificationRecord { - final StatusBarNotification sbn; - SingleNotificationStats stats; - boolean isCanceled; - - // These members are used by NotificationSignalExtractors - // to communicate with the ranking module. - private float mContactAffinity; - private boolean mRecentlyIntrusive; - - NotificationRecord(StatusBarNotification sbn) - { - this.sbn = sbn; - } - - public Notification getNotification() { return sbn.getNotification(); } - public int getFlags() { return sbn.getNotification().flags; } - public int getUserId() { return sbn.getUserId(); } - public String getKey() { return sbn.getKey(); } - - void dump(PrintWriter pw, String prefix, Context baseContext) { - final Notification notification = sbn.getNotification(); - pw.println(prefix + this); - pw.println(prefix + " uid=" + sbn.getUid() + " userId=" + sbn.getUserId()); - pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon) - + " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon)); - pw.println(prefix + " pri=" + notification.priority + " score=" + sbn.getScore()); - pw.println(prefix + " key=" + sbn.getKey()); - pw.println(prefix + " contentIntent=" + notification.contentIntent); - pw.println(prefix + " deleteIntent=" + notification.deleteIntent); - pw.println(prefix + " tickerText=" + notification.tickerText); - pw.println(prefix + " contentView=" + notification.contentView); - pw.println(prefix + String.format(" defaults=0x%08x flags=0x%08x", - notification.defaults, notification.flags)); - pw.println(prefix + " sound=" + notification.sound); - pw.println(prefix + String.format(" color=0x%08x", notification.color)); - pw.println(prefix + " vibrate=" + Arrays.toString(notification.vibrate)); - pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d", - notification.ledARGB, notification.ledOnMS, notification.ledOffMS)); - if (notification.actions != null && notification.actions.length > 0) { - pw.println(prefix + " actions={"); - final int N = notification.actions.length; - for (int i=0; i<N; i++) { - final Notification.Action action = notification.actions[i]; - pw.println(String.format("%s [%d] \"%s\" -> %s", - prefix, - i, - action.title, - action.actionIntent.toString() - )); - } - pw.println(prefix + " }"); - } - if (notification.extras != null && notification.extras.size() > 0) { - pw.println(prefix + " extras={"); - for (String key : notification.extras.keySet()) { - pw.print(prefix + " " + key + "="); - Object val = notification.extras.get(key); - if (val == null) { - pw.println("null"); - } else { - pw.print(val.getClass().getSimpleName()); - if (val instanceof CharSequence || val instanceof String) { - // redact contents from bugreports - } else if (val instanceof Bitmap) { - pw.print(String.format(" (%dx%d)", - ((Bitmap) val).getWidth(), - ((Bitmap) val).getHeight())); - } else if (val.getClass().isArray()) { - final int N = Array.getLength(val); - pw.println(" (" + N + ")"); - } else { - pw.print(" (" + String.valueOf(val) + ")"); - } - pw.println(); - } - } - pw.println(prefix + " }"); - } - pw.println(prefix + " stats=" + stats.toString()); - pw.println(prefix + " mContactAffinity=" + mContactAffinity); - pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive); - } - - @Override - public final String toString() { - return String.format( - "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)", - System.identityHashCode(this), - this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(), - this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(), - this.sbn.getNotification()); - } - - public void setContactAffinity(float contactAffinity) { - mContactAffinity = contactAffinity; - } - - public float getContactAffinity() { - return mContactAffinity; - } - - public void setRecentlyIntusive(boolean recentlyIntrusive) { - mRecentlyIntrusive = recentlyIntrusive; - } - - public boolean isRecentlyIntrusive() { - return mRecentlyIntrusive; - } - } - private static final class ToastRecord { final int pid; @@ -1657,15 +1513,15 @@ public class NotificationManagerService extends SystemService { return; } - // Is this notification intercepted by zen mode? - final boolean intercept = mZenModeHelper.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 || intercept) Slog.v(TAG, - "pkg=" + pkg + " canInterrupt=" + canInterrupt + " intercept=" + intercept); synchronized (mNotificationList) { + applyZenModeLocked(r); + + // Should this notification make noise, vibe, or use the LED? + final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) && + !r.isIntercepted(); + if (DBG || r.isIntercepted()) Slog.v(TAG, + "pkg=" + pkg + " canInterrupt=" + canInterrupt + + " intercept=" + r.isIntercepted()); NotificationRecord old = null; int index = indexOfNotificationLocked(n.getKey()); if (index < 0) { @@ -1678,6 +1534,8 @@ public class NotificationManagerService extends SystemService { // Make sure we don't lose the foreground service state. notification.flags |= old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE; + // Retain ranking information from previous record + r.copyRankingInformation(old); mNotificationsByKey.remove(old.sbn.getKey()); } mNotificationsByKey.put(n.getKey(), r); @@ -1724,7 +1582,7 @@ public class NotificationManagerService extends SystemService { sendAccessibilityEvent(notification, pkg); } - mListeners.notifyPostedLocked(r.sbn, cloneNotificationListLocked()); + mListeners.notifyPostedLocked(r.sbn); } else { Slog.e(TAG, "Not posting notification with icon==0: " + notification); if (old != null && !old.isCanceled) { @@ -1735,7 +1593,7 @@ public class NotificationManagerService extends SystemService { Binder.restoreCallingIdentity(identity); } - mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked()); + mListeners.notifyRemovedLocked(r.sbn); } // ATTENTION: in a future release we will bail out here // so that we do not play sounds, show lights, etc. for invalid @@ -1992,23 +1850,32 @@ public class NotificationManagerService extends SystemService { if (!(message.obj instanceof RankingReconsideration)) return; RankingReconsideration recon = (RankingReconsideration) message.obj; recon.run(); - boolean orderChanged; + boolean changed; synchronized (mNotificationList) { final NotificationRecord record = mNotificationsByKey.get(recon.getKey()); if (record == null) { return; } - int before = findNotificationRecordIndexLocked(record); + int indexBefore = findNotificationRecordIndexLocked(record); + boolean interceptBefore = record.isIntercepted(); recon.applyChangesLocked(record); + applyZenModeLocked(record); Collections.sort(mNotificationList, mRankingComparator); - int after = findNotificationRecordIndexLocked(record); - orderChanged = before != after; + int indexAfter = findNotificationRecordIndexLocked(record); + boolean interceptAfter = record.isIntercepted(); + changed = indexBefore != indexAfter || interceptBefore != interceptAfter; } - if (orderChanged) { + if (changed) { scheduleSendRankingUpdate(); } } + // let zen mode evaluate this record and then make note of that for the future + private void applyZenModeLocked(NotificationRecord record) { + record.setIntercepted(mZenModeHelper.shouldIntercept(record, record.wasTouchedByZen())); + record.setTouchedByZen(); + } + // lock on mNotificationList private int findNotificationRecordIndexLocked(NotificationRecord target) { return Collections.binarySearch(mNotificationList, target, mRankingComparator); @@ -2022,19 +1889,10 @@ public class NotificationManagerService extends SystemService { private void handleSendRankingUpdate() { synchronized (mNotificationList) { - mListeners.notifyRankingUpdateLocked(cloneNotificationListLocked()); + mListeners.notifyRankingUpdateLocked(); } } - private ArrayList<StatusBarNotification> cloneNotificationListLocked() { - final int N = mNotificationList.size(); - ArrayList<StatusBarNotification> sbns = new ArrayList<StatusBarNotification>(N); - for (int i = 0; i < N; i++) { - sbns.add(mNotificationList.get(i).sbn); - } - return sbns; - } - private final class WorkerHandler extends Handler { @Override @@ -2120,7 +1978,7 @@ public class NotificationManagerService extends SystemService { Binder.restoreCallingIdentity(identity); } r.isCanceled = true; - mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked()); + mListeners.notifyRemovedLocked(r.sbn); } // sound @@ -2441,22 +2299,25 @@ public class NotificationManagerService extends SystemService { /** * Generates a NotificationRankingUpdate from 'sbns', considering only * notifications visible to the given listener. + * + * <p>Caller must hold a lock on mNotificationList.</p> */ - private static NotificationRankingUpdate makeRankingUpdateForListener(ManagedServiceInfo info, - ArrayList<StatusBarNotification> sbns) { + private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) { int speedBumpIndex = -1; - ArrayList<String> keys = new ArrayList<String>(sbns.size()); - ArrayList<String> dndKeys = new ArrayList<String>(sbns.size()); - for (StatusBarNotification sbn: sbns) { - if (!info.enabledAndUserMatches(sbn.getUserId())) { + final int N = mNotificationList.size(); + ArrayList<String> keys = new ArrayList<String>(N); + ArrayList<String> dndKeys = new ArrayList<String>(N); + for (int i = 0; i < N; i++) { + NotificationRecord record = mNotificationList.get(i); + if (!info.enabledAndUserMatches(record.sbn.getUserId())) { continue; } - keys.add(sbn.getKey()); - if (sbn.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) { - dndKeys.add(sbn.getKey()); + keys.add(record.sbn.getKey()); + if (record.isIntercepted()) { + dndKeys.add(record.sbn.getKey()); } if (speedBumpIndex == -1 && - sbn.getNotification().priority == Notification.PRIORITY_MIN) { + record.sbn.getNotification().priority == Notification.PRIORITY_MIN) { speedBumpIndex = keys.size() - 1; } } @@ -2491,12 +2352,12 @@ public class NotificationManagerService extends SystemService { @Override public void onServiceAdded(ManagedServiceInfo info) { final INotificationListener listener = (INotificationListener) info.service; - final ArrayList<StatusBarNotification> sbns; + final NotificationRankingUpdate update; synchronized (mNotificationList) { - sbns = cloneNotificationListLocked(); + update = makeRankingUpdateLocked(info); } try { - listener.onListenerConnected(makeRankingUpdateForListener(info, sbns)); + listener.onListenerConnected(update); } catch (RemoteException e) { // we tried } @@ -2505,15 +2366,14 @@ public class NotificationManagerService extends SystemService { /** * asynchronously notify all listeners about a new notification */ - public void notifyPostedLocked(StatusBarNotification sbn, - final ArrayList<StatusBarNotification> sbns) { + public void notifyPostedLocked(StatusBarNotification sbn) { // make a copy in case changes are made to the underlying Notification object final StatusBarNotification sbnClone = sbn.clone(); for (final ManagedServiceInfo info : mServices) { if (!info.isEnabledForCurrentProfiles()) { continue; } - final NotificationRankingUpdate update = makeRankingUpdateForListener(info, sbns); + final NotificationRankingUpdate update = makeRankingUpdateLocked(info); if (update.getOrderedKeys().length == 0) { continue; } @@ -2529,8 +2389,7 @@ public class NotificationManagerService extends SystemService { /** * asynchronously notify all listeners about a removed notification */ - public void notifyRemovedLocked(StatusBarNotification sbn, - final ArrayList<StatusBarNotification> sbns) { + public void notifyRemovedLocked(StatusBarNotification sbn) { // make a copy in case changes are made to the underlying Notification object // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the // notification @@ -2539,11 +2398,11 @@ public class NotificationManagerService extends SystemService { if (!info.isEnabledForCurrentProfiles()) { continue; } + final NotificationRankingUpdate update = makeRankingUpdateLocked(info); mHandler.post(new Runnable() { @Override public void run() { - notifyRemovedIfUserMatch(info, sbnLight, - makeRankingUpdateForListener(info, sbns)); + notifyRemovedIfUserMatch(info, sbnLight, update); } }); } @@ -2551,20 +2410,18 @@ public class NotificationManagerService extends SystemService { /** * asynchronously notify all listeners about a reordering of notifications - * @param sbns an array of {@link StatusBarNotification}s to consider. This code - * must not rely on mutable members of these objects, such as the - * {@link Notification}. */ - public void notifyRankingUpdateLocked(final ArrayList<StatusBarNotification> sbns) { + public void notifyRankingUpdateLocked() { for (final ManagedServiceInfo serviceInfo : mServices) { if (!serviceInfo.isEnabledForCurrentProfiles()) { continue; } + final NotificationRankingUpdate update = + makeRankingUpdateLocked(serviceInfo); mHandler.post(new Runnable() { @Override public void run() { - notifyRankingUpdate(serviceInfo, - makeRankingUpdateForListener(serviceInfo, sbns)); + notifyRankingUpdate(serviceInfo, update); } }); } diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java new file mode 100644 index 0000000..08f8eb4 --- /dev/null +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -0,0 +1,204 @@ +/* + * 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.server.notification; + +import android.app.Notification; +import android.content.Context; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.service.notification.StatusBarNotification; + +import java.io.PrintWriter; +import java.lang.reflect.Array; +import java.util.Arrays; + +/** + * Holds data about notifications that should not be shared with the + * {@link android.service.notification.NotificationListenerService}s. + * + * <p>These objects should not be mutated unless the code is synchronized + * on {@link NotificationManagerService#mNotificationList}, and any + * modification should be followed by a sorting of that list.</p> + * + * <p>Is sortable by {@link NotificationComparator}.</p> + * + * {@hide} + */ +public final class NotificationRecord { + final StatusBarNotification sbn; + NotificationUsageStats.SingleNotificationStats stats; + boolean isCanceled; + + // These members are used by NotificationSignalExtractors + // to communicate with the ranking module. + private float mContactAffinity; + private boolean mRecentlyIntrusive; + + // is this notification currently being intercepted by Zen Mode? + private boolean mIntercept; + // InterceptedNotifications needs to know if this has been previously evaluated. + private boolean mTouchedByZen; + + NotificationRecord(StatusBarNotification sbn) + { + this.sbn = sbn; + } + + // copy any notes that the ranking system may have made before the update + public void copyRankingInformation(NotificationRecord previous) { + mContactAffinity = previous.mContactAffinity; + mRecentlyIntrusive = previous.mRecentlyIntrusive; + mTouchedByZen = previous.mTouchedByZen; + mIntercept = previous.mIntercept; + } + + public Notification getNotification() { return sbn.getNotification(); } + public int getFlags() { return sbn.getNotification().flags; } + public int getUserId() { return sbn.getUserId(); } + public String getKey() { return sbn.getKey(); } + + void dump(PrintWriter pw, String prefix, Context baseContext) { + final Notification notification = sbn.getNotification(); + pw.println(prefix + this); + pw.println(prefix + " uid=" + sbn.getUid() + " userId=" + sbn.getUserId()); + pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon) + + " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon)); + pw.println(prefix + " pri=" + notification.priority + " score=" + sbn.getScore()); + pw.println(prefix + " key=" + sbn.getKey()); + pw.println(prefix + " contentIntent=" + notification.contentIntent); + pw.println(prefix + " deleteIntent=" + notification.deleteIntent); + pw.println(prefix + " tickerText=" + notification.tickerText); + pw.println(prefix + " contentView=" + notification.contentView); + pw.println(prefix + String.format(" defaults=0x%08x flags=0x%08x", + notification.defaults, notification.flags)); + pw.println(prefix + " sound=" + notification.sound); + pw.println(prefix + String.format(" color=0x%08x", notification.color)); + pw.println(prefix + " vibrate=" + Arrays.toString(notification.vibrate)); + pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d", + notification.ledARGB, notification.ledOnMS, notification.ledOffMS)); + if (notification.actions != null && notification.actions.length > 0) { + pw.println(prefix + " actions={"); + final int N = notification.actions.length; + for (int i=0; i<N; i++) { + final Notification.Action action = notification.actions[i]; + pw.println(String.format("%s [%d] \"%s\" -> %s", + prefix, + i, + action.title, + action.actionIntent.toString() + )); + } + pw.println(prefix + " }"); + } + if (notification.extras != null && notification.extras.size() > 0) { + pw.println(prefix + " extras={"); + for (String key : notification.extras.keySet()) { + pw.print(prefix + " " + key + "="); + Object val = notification.extras.get(key); + if (val == null) { + pw.println("null"); + } else { + pw.print(val.getClass().getSimpleName()); + if (val instanceof CharSequence || val instanceof String) { + // redact contents from bugreports + } else if (val instanceof Bitmap) { + pw.print(String.format(" (%dx%d)", + ((Bitmap) val).getWidth(), + ((Bitmap) val).getHeight())); + } else if (val.getClass().isArray()) { + final int N = Array.getLength(val); + pw.println(" (" + N + ")"); + } else { + pw.print(" (" + String.valueOf(val) + ")"); + } + pw.println(); + } + } + pw.println(prefix + " }"); + } + pw.println(prefix + " stats=" + stats.toString()); + pw.println(prefix + " mContactAffinity=" + mContactAffinity); + pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive); + pw.println(prefix + " mIntercept=" + mIntercept); + } + + + static String idDebugString(Context baseContext, String packageName, int id) { + Context c; + + if (packageName != null) { + try { + c = baseContext.createPackageContext(packageName, 0); + } catch (NameNotFoundException e) { + c = baseContext; + } + } else { + c = baseContext; + } + + Resources r = c.getResources(); + try { + return r.getResourceName(id); + } catch (Resources.NotFoundException e) { + return "<name unknown>"; + } + } + + @Override + public final String toString() { + return String.format( + "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)", + System.identityHashCode(this), + this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(), + this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(), + this.sbn.getNotification()); + } + + public void setContactAffinity(float contactAffinity) { + mContactAffinity = contactAffinity; + } + + public float getContactAffinity() { + return mContactAffinity; + } + + public void setRecentlyIntusive(boolean recentlyIntrusive) { + mRecentlyIntrusive = recentlyIntrusive; + } + + public boolean isRecentlyIntrusive() { + return mRecentlyIntrusive; + } + + public boolean setIntercepted(boolean intercept) { + mIntercept = intercept; + return mIntercept; + } + + public boolean isIntercepted() { + return mIntercept; + } + + public boolean wasTouchedByZen() { + return mTouchedByZen; + } + + public void setTouchedByZen() { + mTouchedByZen = true; + } + +} diff --git a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java index 71c819e..1537ea9 100644 --- a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java @@ -18,11 +18,9 @@ package com.android.server.notification; import android.content.Context; -import com.android.server.notification.NotificationManagerService.NotificationRecord; - /** * Extracts signals that will be useful to the {@link NotificationComparator} and caches them - * on the {@link NotificationManagerService.NotificationRecord} object. These annotations will + * on the {@link NotificationRecord} object. These annotations will * not be passed on to {@link android.service.notification.NotificationListenerService}s. */ public interface NotificationSignalExtractor { diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java index 66cc532..bab4895 100644 --- a/services/core/java/com/android/server/notification/NotificationUsageStats.java +++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java @@ -16,8 +16,6 @@ package com.android.server.notification; -import com.android.server.notification.NotificationManagerService.NotificationRecord; - import android.content.ContentValues; import android.content.Context; import android.database.Cursor; diff --git a/services/core/java/com/android/server/notification/RankingReconsideration.java b/services/core/java/com/android/server/notification/RankingReconsideration.java index cf5e210..057f0f1 100644 --- a/services/core/java/com/android/server/notification/RankingReconsideration.java +++ b/services/core/java/com/android/server/notification/RankingReconsideration.java @@ -15,8 +15,6 @@ */ package com.android.server.notification; -import com.android.server.notification.NotificationManagerService.NotificationRecord; - import java.util.concurrent.TimeUnit; /** diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java index a629a5f..02f95e9 100644 --- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java +++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java @@ -28,8 +28,6 @@ import android.text.TextUtils; import android.util.LruCache; import android.util.Slog; -import com.android.server.notification.NotificationManagerService.NotificationRecord; - import java.util.ArrayList; import java.util.LinkedList; @@ -49,9 +47,20 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { private static final int MAX_PEOPLE = 10; private static final int PEOPLE_CACHE_SIZE = 200; - private static final float NONE = 0f; - private static final float VALID_CONTACT = 0.5f; - private static final float STARRED_CONTACT = 1f; + /** Indicates that the notification does not reference any valid contacts. */ + static final float NONE = 0f; + + /** + * Affinity will be equal to or greater than this value on notifications + * that reference a valid contact. + */ + static final float VALID_CONTACT = 0.5f; + + /** + * Affinity will be equal to or greater than this value on notifications + * that reference a starred contact. + */ + static final float STARRED_CONTACT = 1f; protected boolean mEnabled; private Context mContext; diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 154ac96..50a32c4 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -18,7 +18,6 @@ package com.android.server.notification; import android.app.AlarmManager; import android.app.AppOpsManager; -import android.app.Notification; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -78,11 +77,13 @@ public class ZenModeHelper { // 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" + "com.android.phone", + "com.android.example.notificationshowcase" )); private static final Set<String> MESSAGE_PACKAGES = new HashSet<String>(Arrays.asList( "com.google.android.talk", - "com.android.mms" + "com.android.mms", + "com.android.example.notificationshowcase" )); private static final Set<String> ALARM_PACKAGES = new HashSet<String>(Arrays.asList( "com.google.android.deskclock" @@ -123,15 +124,23 @@ public class ZenModeHelper { mCallbacks.add(callback); } - public boolean shouldIntercept(String pkg, Notification n) { + public boolean shouldIntercept(NotificationRecord record, boolean previouslySeen) { if (mZenMode != Global.ZEN_MODE_OFF) { - if (isAlarm(pkg, n)) { + if (previouslySeen && !record.isIntercepted()) { + // notifications never transition from not intercepted to intercepted return false; } - if (isCall(pkg, n)) { + if (isAlarm(record)) { + return false; + } + // audience has veto power over all following rules + if (!audienceMatches(record)) { + return true; + } + if (isCall(record)) { return !mConfig.allowCalls; } - if (isMessage(pkg, n)) { + if (isMessage(record)) { return !mConfig.allowMessages; } return true; @@ -176,7 +185,8 @@ public class ZenModeHelper { } public boolean allowDisable(int what, IBinder token, String pkg) { - if (isCall(pkg, null)) { + // TODO(cwren): delete this API before the next release. Bug:15344099 + if (CALL_PACKAGES.contains(pkg)) { return mZenMode == Global.ZEN_MODE_OFF || mConfig.allowCalls; } return true; @@ -229,16 +239,30 @@ public class ZenModeHelper { } } - private boolean isAlarm(String pkg, Notification n) { - return ALARM_PACKAGES.contains(pkg); + private boolean isAlarm(NotificationRecord record) { + return ALARM_PACKAGES.contains(record.sbn.getPackageName()); } - private boolean isCall(String pkg, Notification n) { - return CALL_PACKAGES.contains(pkg); + private boolean isCall(NotificationRecord record) { + return CALL_PACKAGES.contains(record.sbn.getPackageName()); } - private boolean isMessage(String pkg, Notification n) { - return MESSAGE_PACKAGES.contains(pkg); + private boolean isMessage(NotificationRecord record) { + return MESSAGE_PACKAGES.contains(record.sbn.getPackageName()); + } + + private boolean audienceMatches(NotificationRecord record) { + switch (mConfig.allowFrom) { + case ZenModeConfig.SOURCE_ANYONE: + return true; + case ZenModeConfig.SOURCE_CONTACT: + return record.getContactAffinity() >= ValidateNotificationPeople.VALID_CONTACT; + case ZenModeConfig.SOURCE_STAR: + return record.getContactAffinity() >= ValidateNotificationPeople.STARRED_CONTACT; + default: + Slog.w(TAG, "Encountered unknown source: " + mConfig.allowFrom); + return true; + } } private void updateAlarms() { diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 6fdd535..008d2fc 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -284,7 +284,7 @@ public class WindowAnimator { } else if (mKeyguardGoingAway && !nowAnimating) { // Timeout!! Slog.e(TAG, "Timeout waiting for animation to startup"); - mPolicy.startKeyguardExitAnimation(0); + mPolicy.startKeyguardExitAnimation(0, 0); mKeyguardGoingAway = false; } if (win.isReadyForDisplay()) { @@ -392,7 +392,9 @@ public class WindowAnimator { winAnimator.mAnimationIsEntrance = true; if (startKeyguardExit) { // Do one time only. - mPolicy.startKeyguardExitAnimation(a.getStartOffset()); + mPolicy.startKeyguardExitAnimation(mCurrentTime + a.getStartOffset(), + a.getDuration()); + mKeyguardGoingAway = false; startKeyguardExit = false; } } |