Merge "Move localeScriptWasProvided to end of ResTable_config"
diff --git a/core/java/com/android/internal/os/KernelCpuSpeedReader.java b/core/java/com/android/internal/os/KernelCpuSpeedReader.java
index 5b776ac..3f6ebb9 100644
--- a/core/java/com/android/internal/os/KernelCpuSpeedReader.java
+++ b/core/java/com/android/internal/os/KernelCpuSpeedReader.java
@@ -16,8 +16,11 @@
package com.android.internal.os;
import android.text.TextUtils;
+import android.system.OsConstants;
import android.util.Slog;
+import libcore.io.Libcore;
+
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
@@ -29,7 +32,7 @@
*
* freq time
*
- * where time is measured in 1/100 seconds.
+ * where time is measured in jiffies.
*/
public class KernelCpuSpeedReader {
private static final String TAG = "KernelCpuSpeedReader";
@@ -38,6 +41,9 @@
private final long[] mLastSpeedTimes;
private final long[] mDeltaSpeedTimes;
+ // How long a CPU jiffy is in milliseconds.
+ private final long mJiffyMillis;
+
/**
* @param cpuNumber The cpu (cpu0, cpu1, etc) whose state to read.
*/
@@ -46,6 +52,8 @@
cpuNumber);
mLastSpeedTimes = new long[numSpeedSteps];
mDeltaSpeedTimes = new long[numSpeedSteps];
+ long jiffyHz = Libcore.os.sysconf(OsConstants._SC_CLK_TCK);
+ mJiffyMillis = 1000/jiffyHz;
}
/**
@@ -62,8 +70,7 @@
splitter.setString(line);
Long.parseLong(splitter.next());
- // The proc file reports time in 1/100 sec, so convert to milliseconds.
- long time = Long.parseLong(splitter.next()) * 10;
+ long time = Long.parseLong(splitter.next()) * mJiffyMillis;
if (time < mLastSpeedTimes[speedIndex]) {
// The stats reset when the cpu hotplugged. That means that the time
// we read is offset from 0, so the time is the delta.
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index bf97f1f..d831902 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -67,10 +67,10 @@
static final int PROCESS_STAT_UTIME = 2;
static final int PROCESS_STAT_STIME = 3;
- /** Stores user time and system time in 100ths of a second. */
+ /** Stores user time and system time in jiffies. */
private final long[] mProcessStatsData = new long[4];
- /** Stores user time and system time in 100ths of a second. Used for
+ /** Stores user time and system time in jiffies. Used for
* public API to retrieve CPU use for a process. Must lock while in use. */
private final long[] mSinglePidStatsData = new long[4];
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 409f6a7..c7d17dc 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -18,6 +18,7 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
+import android.auditing.SecurityLog;
import android.content.Context;
import android.os.UserHandle;
import android.util.AttributeSet;
@@ -423,6 +424,11 @@
}
public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
+ if (SecurityLog.isLoggingEnabled()) {
+ SecurityLog.writeEvent(SecurityLog.TAG_DEVICE_UNLOCK_ATTEMPT,
+ (success ? 1 : 0),
+ mCurrentSecuritySelection.name());
+ }
KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
if (success) {
monitor.clearFailedUnlockAttempts();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 9a00b4b..704de97 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -24,6 +24,7 @@
import android.app.SearchManager;
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
+import android.auditing.SecurityLog;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -1352,6 +1353,11 @@
* @see #KEYGUARD_DONE
*/
private void handleKeyguardDone(boolean authenticated) {
+ if (SecurityLog.isLoggingEnabled()
+ && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
+ SecurityLog.writeEvent(SecurityLog.TAG_DEVICE_UNLOCK_ATTEMPT,
+ (authenticated ? 1 : 0), "Unknown");
+ }
if (DEBUG) Log.d(TAG, "handleKeyguardDone");
synchronized (this) {
resetKeyguardDonePendingLocked();
@@ -1463,6 +1469,10 @@
* @see #SHOW
*/
private void handleShow(Bundle options) {
+ if (SecurityLog.isLoggingEnabled()
+ && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
+ SecurityLog.writeEvent(SecurityLog.TAG_DEVICE_LOCKED, "");
+ }
synchronized (KeyguardViewMediator.this) {
if (!mSystemReady) {
if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index adb11a4..8c2090e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -20899,7 +20899,9 @@
}
public boolean isUserStopped(int userId) {
- return mUserController.getStartedUserStateLocked(userId) == null;
+ synchronized (this) {
+ return mUserController.getStartedUserStateLocked(userId) == null;
+ }
}
ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) {
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index a3c26cb..05702af 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -77,8 +77,8 @@
}
/**
- * Loads the persistent recentTasks for {@code userId} into {@link #mRecentTasks} from
- * persistent storage. Does nothing if they are already loaded.
+ * Loads the persistent recentTasks for {@code userId} into this list from persistent storage.
+ * Does nothing if they are already loaded.
*
* @param userId the user Id
*/
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index f360dc2..f5da52e 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -297,7 +297,6 @@
checkType(guest.service);
if (registerServiceImpl(guest) != null) {
onServiceAdded(guest);
- onServiceAdded(guest);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b1fe68c..2ee74db 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -223,6 +223,8 @@
private WorkerHandler mHandler;
private final HandlerThread mRankingThread = new HandlerThread("ranker",
Process.THREAD_PRIORITY_BACKGROUND);
+ private final HandlerThread mAssistantThread = new HandlerThread("assistant",
+ Process.THREAD_PRIORITY_BACKGROUND);
private Light mNotificationLight;
Light mAttentionLight;
@@ -295,6 +297,7 @@
private static final int MY_UID = Process.myUid();
private static final int MY_PID = Process.myPid();
private RankingHandler mRankingHandler;
+ private Handler mAssistantHandler;
private static class Archive {
final int mBufferSize;
@@ -878,6 +881,7 @@
mHandler = new WorkerHandler();
mRankingThread.start();
+ mAssistantThread.start();
String[] extractorNames;
try {
extractorNames = resources.getStringArray(R.array.config_notificationSignalExtractors);
@@ -886,6 +890,7 @@
}
mUsageStats = new NotificationUsageStats(getContext());
mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper());
+ mAssistantHandler = new Handler(mAssistantThread.getLooper());
mRankingHelper = new RankingHelper(getContext(),
mRankingHandler,
mUsageStats,
@@ -1957,7 +1962,7 @@
@Override
public void setImportanceFromAssistant(INotificationListener token, String key,
- int importance, CharSequence explanation) {
+ int importance, CharSequence explanation) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mNotificationList) {
@@ -2249,115 +2254,145 @@
+ " id=" + id + " notification=" + notification);
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
+ // Sanitize inputs
+ notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
+ Notification.PRIORITY_MAX);
- synchronized (mNotificationList) {
-
- // Sanitize inputs
- notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
- Notification.PRIORITY_MAX);
-
- // setup local book-keeping
- final StatusBarNotification n = new StatusBarNotification(
- pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
- user);
- NotificationRecord r = new NotificationRecord(getContext(), n);
- NotificationRecord old = mNotificationsByKey.get(n.getKey());
- if (old != null) {
- // Retain ranking information from previous record
- r.copyRankingInformation(old);
- }
-
- // Handle grouped notifications and bail out early if we
- // can to avoid extracting signals.
- handleGroupedNotificationLocked(r, old, callingUid, callingPid);
- boolean ignoreNotification =
- removeUnusedGroupedNotificationLocked(r, old, callingUid, callingPid);
-
- // This conditional is a dirty hack to limit the logging done on
- // behalf of the download manager without affecting other apps.
- if (!pkg.equals("com.android.providers.downloads")
- || Log.isLoggable("DownloadManager", Log.VERBOSE)) {
- int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW;
- if (ignoreNotification) {
- enqueueStatus = EVENTLOG_ENQUEUE_STATUS_IGNORED;
- } else if (old != null) {
- enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;
- }
- EventLogTags.writeNotificationEnqueue(callingUid, callingPid,
- pkg, id, tag, userId, notification.toString(),
- enqueueStatus);
- }
-
- if (ignoreNotification) {
- return;
- }
-
- mRankingHelper.extractSignals(r);
- savePolicyFile();
-
- // blocked apps/topics
- if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE
- || !noteNotificationOp(pkg, callingUid)) {
- if (!isSystemNotification) {
- Slog.e(TAG, "Suppressing notification from package " + pkg
- + " by user request.");
- mUsageStats.registerBlocked(r);
- return;
- }
- }
-
- int index = indexOfNotificationLocked(n.getKey());
- if (index < 0) {
- mNotificationList.add(r);
- mUsageStats.registerPostedByApp(r);
- } else {
- old = mNotificationList.get(index);
- mNotificationList.set(index, r);
- mUsageStats.registerUpdatedByApp(r, old);
- // Make sure we don't lose the foreground service state.
- notification.flags |=
- old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
- r.isUpdate = true;
- }
-
- mNotificationsByKey.put(n.getKey(), r);
-
- // Ensure if this is a foreground service that the proper additional
- // flags are set.
- if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
- notification.flags |= Notification.FLAG_ONGOING_EVENT
- | Notification.FLAG_NO_CLEAR;
- }
-
- applyZenModeLocked(r);
- mRankingHelper.sort(mNotificationList);
-
- if (notification.getSmallIcon() != null) {
- StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
- mListeners.notifyPostedLocked(n, oldSbn);
- } else {
- Slog.e(TAG, "Not posting notification without small icon: " + notification);
- if (old != null && !old.isCanceled) {
- mListeners.notifyRemovedLocked(n);
- }
- // ATTENTION: in a future release we will bail out here
- // so that we do not play sounds, show lights, etc. for invalid
- // notifications
- Slog.e(TAG, "WARNING: In a future release this will crash the app: "
- + n.getPackageName());
- }
-
- buzzBeepBlinkLocked(r);
- }
- }
- });
+ // setup local book-keeping
+ final StatusBarNotification n = new StatusBarNotification(
+ pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
+ user);
+ final NotificationRecord r = new NotificationRecord(getContext(), n);
+ mHandler.post(new EnqueueNotificationRunnable(userId, r));
idOut[0] = id;
}
+ private class EnqueueNotificationRunnable implements Runnable {
+ private final NotificationRecord r;
+ private final int userId;
+
+ EnqueueNotificationRunnable(int userId, NotificationRecord r) {
+ this.userId = userId;
+ this.r = r;
+ };
+
+ @Override
+ public void run() {
+
+ synchronized (mNotificationList) {
+ final StatusBarNotification n = r.sbn;
+ Slog.d(TAG, "EnqueueNotificationRunnable.run for: " + n.getKey());
+ NotificationRecord old = mNotificationsByKey.get(n.getKey());
+ if (old != null) {
+ // Retain ranking information from previous record
+ r.copyRankingInformation(old);
+ }
+
+ final int callingUid = n.getUid();
+ final int callingPid = n.getInitialPid();
+ final Notification notification = n.getNotification();
+ final String pkg = n.getPackageName();
+ final int id = n.getId();
+ final String tag = n.getTag();
+ final boolean isSystemNotification = isUidSystem(callingUid) ||
+ ("android".equals(pkg));
+
+ // Handle grouped notifications and bail out early if we
+ // can to avoid extracting signals.
+ handleGroupedNotificationLocked(r, old, callingUid, callingPid);
+ boolean ignoreNotification =
+ removeUnusedGroupedNotificationLocked(r, old, callingUid, callingPid);
+ Slog.d(TAG, "ignoreNotification is " + ignoreNotification);
+
+ // This conditional is a dirty hack to limit the logging done on
+ // behalf of the download manager without affecting other apps.
+ if (!pkg.equals("com.android.providers.downloads")
+ || Log.isLoggable("DownloadManager", Log.VERBOSE)) {
+ int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW;
+ if (ignoreNotification) {
+ enqueueStatus = EVENTLOG_ENQUEUE_STATUS_IGNORED;
+ } else if (old != null) {
+ enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;
+ }
+ EventLogTags.writeNotificationEnqueue(callingUid, callingPid,
+ pkg, id, tag, userId, notification.toString(),
+ enqueueStatus);
+ }
+
+ if (ignoreNotification) {
+ return;
+ }
+
+ mRankingHelper.extractSignals(r);
+
+ // why is this here?
+ savePolicyFile();
+
+ // blocked apps/topics
+ if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE
+ || !noteNotificationOp(pkg, callingUid)) {
+ if (!isSystemNotification) {
+ Slog.e(TAG, "Suppressing notification from package " + pkg
+ + " by user request.");
+ mUsageStats.registerBlocked(r);
+ return;
+ }
+ }
+
+ // tell the assistant about the notification
+ if (mAssistant.isEnabled()) {
+ mAssistant.onNotificationEnqueued(r);
+ // TODO delay the code below here for 100ms or until there is an answer
+ }
+
+
+ int index = indexOfNotificationLocked(n.getKey());
+ if (index < 0) {
+ mNotificationList.add(r);
+ mUsageStats.registerPostedByApp(r);
+ } else {
+ old = mNotificationList.get(index);
+ mNotificationList.set(index, r);
+ mUsageStats.registerUpdatedByApp(r, old);
+ // Make sure we don't lose the foreground service state.
+ notification.flags |=
+ old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
+ r.isUpdate = true;
+ }
+
+ mNotificationsByKey.put(n.getKey(), r);
+
+ // Ensure if this is a foreground service that the proper additional
+ // flags are set.
+ if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+ notification.flags |= Notification.FLAG_ONGOING_EVENT
+ | Notification.FLAG_NO_CLEAR;
+ }
+
+ applyZenModeLocked(r);
+ mRankingHelper.sort(mNotificationList);
+
+ if (notification.getSmallIcon() != null) {
+ StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
+ mListeners.notifyPostedLocked(n, oldSbn);
+ } else {
+ Slog.e(TAG, "Not posting notification without small icon: " + notification);
+ if (old != null && !old.isCanceled) {
+ mListeners.notifyRemovedLocked(n);
+ }
+ // ATTENTION: in a future release we will bail out here
+ // so that we do not play sounds, show lights, etc. for invalid
+ // notifications
+ Slog.e(TAG, "WARNING: In a future release this will crash the app: "
+ + n.getPackageName());
+ }
+
+ buzzBeepBlinkLocked(r);
+ }
+ }
+ }
+
/**
* Ensures that grouped notification receive their special treatment.
*
@@ -3391,6 +3426,30 @@
return true;
}
+ private class TrimCache {
+ StatusBarNotification heavy;
+ StatusBarNotification sbnClone;
+ StatusBarNotification sbnCloneLight;
+
+ TrimCache(StatusBarNotification sbn) {
+ heavy = sbn;
+ }
+
+ StatusBarNotification ForListener(ManagedServiceInfo info) {
+ if (mListeners.getOnNotificationPostedTrim(info) == TRIM_LIGHT) {
+ if (sbnCloneLight == null) {
+ sbnCloneLight = heavy.cloneLight();
+ }
+ return sbnCloneLight;
+ } else {
+ if (sbnClone == null) {
+ sbnClone = heavy.clone();
+ }
+ return sbnClone;
+ }
+ }
+ }
+
public class NotificationAssistant extends ManagedServices {
public NotificationAssistant() {
@@ -3428,6 +3487,46 @@
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
mListeners.unregisterService(removed.service, removed.userid);
}
+
+ public void onNotificationEnqueued(final NotificationRecord r) {
+ final StatusBarNotification sbn = r.sbn;
+ TrimCache trimCache = new TrimCache(sbn);
+
+ // mServices is the list inside ManagedServices of all the assistants,
+ // There should be only one, but it's a list, so while we enforce
+ // singularity elsewhere, we keep it general here, to avoid surprises.
+ for (final ManagedServiceInfo info : NotificationAssistant.this.mServices) {
+ boolean sbnVisible = isVisibleToListener(sbn, info);
+ if (!sbnVisible) {
+ continue;
+ }
+
+ final int importance = r.getImportance();
+ final boolean fromUser = r.isImportanceFromUser();
+ final StatusBarNotification sbnToPost = trimCache.ForListener(info);
+ mAssistantHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyEnqueued(info, sbnToPost, importance, fromUser);
+ }
+ });
+ }
+ }
+
+ private void notifyEnqueued(final ManagedServiceInfo info,
+ final StatusBarNotification sbn, int importance, boolean fromUser) {
+ final INotificationListener assistant = (INotificationListener) info.service;
+ StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
+ try {
+ assistant.onNotificationEnqueued(sbnHolder, importance, fromUser);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
+ }
+ }
+
+ public boolean isEnabled() {
+ return !mServices.isEmpty();
+ }
}
public class NotificationListeners extends ManagedServices {
@@ -3476,7 +3575,6 @@
}
}
-
@Override
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
if (mListenersDisablingEffects.remove(removed)) {
@@ -3508,8 +3606,7 @@
*/
public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) {
// Lazily initialized snapshots of the notification.
- StatusBarNotification sbnClone = null;
- StatusBarNotification sbnCloneLight = null;
+ TrimCache trimCache = new TrimCache(sbn);
for (final ManagedServiceInfo info : mServices) {
boolean sbnVisible = isVisibleToListener(sbn, info);
@@ -3532,16 +3629,7 @@
continue;
}
- final int trim = mListeners.getOnNotificationPostedTrim(info);
-
- if (trim == TRIM_LIGHT && sbnCloneLight == null) {
- sbnCloneLight = sbn.cloneLight();
- } else if (trim == TRIM_FULL && sbnClone == null) {
- sbnClone = sbn.clone();
- }
- final StatusBarNotification sbnToPost =
- (trim == TRIM_FULL) ? sbnClone : sbnCloneLight;
-
+ final StatusBarNotification sbnToPost = trimCache.ForListener(info);
mHandler.post(new Runnable() {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 0be2edd..490e890 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -15,6 +15,7 @@
*/
package com.android.server.notification;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_LOW;
@@ -88,8 +89,8 @@
private int mAuthoritativeRank;
private String mGlobalSortKey;
private int mPackageVisibility;
- private int mTopicImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
- private int mImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ private int mTopicImportance = IMPORTANCE_UNSPECIFIED;
+ private int mImportance = IMPORTANCE_UNSPECIFIED;
private CharSequence mImportanceExplanation = null;
private int mSuppressedVisualEffects = 0;
@@ -510,4 +511,8 @@
public String getGroupKey() {
return sbn.getGroupKey();
}
+
+ public boolean isImportanceFromUser() {
+ return mImportance == mTopicImportance;
+ }
}