Merge "Add a scrubber to keyguard; layout tweaks" into klp-dev
diff --git a/api/current.txt b/api/current.txt
index d050c18..689cdff 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3178,7 +3178,7 @@
method public int noteOpNoThrow(java.lang.String, int, java.lang.String);
method public int startOp(java.lang.String, int, java.lang.String);
method public int startOpNoThrow(java.lang.String, int, java.lang.String);
- method public void startWatchingMode(int, java.lang.String, android.app.AppOpsManager.OnOpChangedListener);
+ method public void startWatchingMode(java.lang.String, java.lang.String, android.app.AppOpsManager.OnOpChangedListener);
method public void stopWatchingMode(android.app.AppOpsManager.OnOpChangedListener);
field public static final int MODE_ALLOWED = 0; // 0x0
field public static final int MODE_ERRORED = 2; // 0x2
@@ -17850,7 +17850,7 @@
field public static final int JELLY_BEAN = 16; // 0x10
field public static final int JELLY_BEAN_MR1 = 17; // 0x11
field public static final int JELLY_BEAN_MR2 = 18; // 0x12
- field public static final int KITKAT = 10000; // 0x2710
+ field public static final int KITKAT = 19; // 0x13
}
public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
@@ -28338,6 +28338,7 @@
field public static final int HAPTIC_FEEDBACK_ENABLED = 268435456; // 0x10000000
field public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0; // 0x0
field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 4; // 0x4
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 059945f..bdc4fdde 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -178,12 +178,13 @@
* If this flag is set the system will regard views that are not important
* for accessibility in addition to the ones that are important for accessibility.
* That is, views that are marked as not important for accessibility via
- * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} and views that are marked as
- * potentially important for accessibility via
+ * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or
+ * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are
+ * marked as potentially important for accessibility via
* {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined
- * that are not important for accessibility, are both reported while querying the
- * window content and also the accessibility service will receive accessibility events
- * from them.
+ * that are not important for accessibility, are reported while querying the window
+ * content and also the accessibility service will receive accessibility events from
+ * them.
* <p>
* <strong>Note:</strong> For accessibility services targeting API version
* {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 02faeac..b364af7 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -533,8 +533,10 @@
private native void dumpGraphicsInfo(FileDescriptor fd);
private class ApplicationThread extends ApplicationThreadNative {
- private static final String HEAP_FULL_COLUMN = "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
- private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s %8s";
+ private static final String HEAP_FULL_COLUMN
+ = "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
+ private static final String HEAP_COLUMN
+ = "%13s %8s %8s %8s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%21s %8d";
private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
@@ -1039,34 +1041,36 @@
// otherwise, show human-readable format
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
- "Shared", "Private", "Heap", "Heap", "Heap");
+ "Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
- "Clean", "Clean", "Size", "Alloc", "Free");
+ "Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
- "------", "------", "------", "------", "------");
+ "------", "------", "------", "------", "------", "------");
printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
- memInfo.nativePrivateClean, nativeMax, nativeAllocated, nativeFree);
+ memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
+ nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
- memInfo.dalvikPrivateClean, dalvikMax, dalvikAllocated, dalvikFree);
+ memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
+ dalvikMax, dalvikAllocated, dalvikFree);
} else {
- printRow(pw, HEAP_COLUMN, "", "Pss", "Pss", "Private",
- "Private", "Heap", "Heap", "Heap");
- printRow(pw, HEAP_COLUMN, "", "Total", "Clean", "Dirty",
- "Clean", "Size", "Alloc", "Free");
+ printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
+ "Private", "Swapped", "Heap", "Heap", "Heap");
+ printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
+ "Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
- "------", "------", "------", "------");
+ "------", "------", "------", "------", "------");
printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
- memInfo.nativeSwappablePss,
memInfo.nativePrivateDirty,
- memInfo.nativePrivateClean, nativeMax, nativeAllocated, nativeFree);
+ memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
+ nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
- memInfo.dalvikSwappablePss,
memInfo.dalvikPrivateDirty,
- memInfo.dalvikPrivateClean, dalvikMax, dalvikAllocated, dalvikFree);
+ memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
+ dalvikMax, dalvikAllocated, dalvikFree);
}
int otherPss = memInfo.otherPss;
@@ -1075,6 +1079,7 @@
int otherPrivateDirty = memInfo.otherPrivateDirty;
int otherSharedClean = memInfo.otherSharedClean;
int otherPrivateClean = memInfo.otherPrivateClean;
+ int otherSwappedOut = memInfo.otherSwappedOut;
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
final int myPss = memInfo.getOtherPss(i);
@@ -1083,16 +1088,17 @@
final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
final int mySharedClean = memInfo.getOtherSharedClean(i);
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
+ final int mySwappedOut = memInfo.getOtherSwappedOut(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
- || mySharedClean != 0 || myPrivateClean != 0) {
+ || mySharedClean != 0 || myPrivateClean != 0 || mySwappedOut != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
- mySharedClean, myPrivateClean, "", "", "");
+ mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
- myPss, mySwappablePss, myPrivateDirty,
- myPrivateClean, "", "", "");
+ myPss, myPrivateDirty,
+ myPrivateClean, mySwappedOut, "", "", "");
}
otherPss -= myPss;
otherSwappablePss -= mySwappablePss;
@@ -1100,27 +1106,28 @@
otherPrivateDirty -= myPrivateDirty;
otherSharedClean -= mySharedClean;
otherPrivateClean -= myPrivateClean;
+ otherSwappedOut -= mySwappedOut;
}
}
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
- "", "", "");
+ otherSwappedOut, "", "", "");
printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
- nativeMax+dalvikMax,
+ memInfo.getTotalSwappedOut(), nativeMax+dalvikMax,
nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
} else {
- printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSwappablePss,
- otherPrivateDirty, otherPrivateClean,
+ printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
+ otherPrivateDirty, otherPrivateClean, otherSwappedOut,
"", "", "");
printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
- memInfo.getTotalSwappablePss(),
memInfo.getTotalPrivateDirty(),
memInfo.getTotalPrivateClean(),
+ memInfo.getTotalSwappedOut(),
nativeMax+dalvikMax,
nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
}
@@ -1137,16 +1144,17 @@
final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
final int mySharedClean = memInfo.getOtherSharedClean(i);
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
+ final int mySwappedOut = memInfo.getOtherSwappedOut(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
|| mySharedClean != 0 || myPrivateClean != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
- mySharedClean, myPrivateClean, "", "", "");
+ mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
- myPss, mySwappablePss, myPrivateDirty,
- myPrivateClean, "", "", "");
+ myPss, myPrivateDirty,
+ myPrivateClean, mySwappedOut, "", "", "");
}
}
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index dce8cab..183927b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -790,9 +790,21 @@
/**
* Monitor for changes to the operating mode for the given op in the given app package.
+ * @param op The operation to monitor, one of OPSTR_*.
+ * @param packageName The name of the application to monitor.
+ * @param callback Where to report changes.
+ */
+ public void startWatchingMode(String op, String packageName,
+ final OnOpChangedListener callback) {
+ startWatchingMode(strOpToOp(op), packageName, callback);
+ }
+
+ /**
+ * Monitor for changes to the operating mode for the given op in the given app package.
* @param op The operation to monitor, one of OP_*.
* @param packageName The name of the application to monitor.
* @param callback Where to report changes.
+ * @hide
*/
public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
synchronized (mModeWatchers) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7183179..190ddb4 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1461,29 +1461,39 @@
}
}
+ private void validateServiceIntent(Intent service) {
+ if (service.getComponent() == null && service.getPackage() == null) {
+ if (true || getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.KITKAT) {
+ Log.w(TAG, "Implicit intents with startService are not safe: " + service
+ + " " + Debug.getCallers(2, 3));
+ //IllegalArgumentException ex = new IllegalArgumentException(
+ // "Service Intent must be explicit: " + service);
+ //Log.e(TAG, "This will become an error", ex);
+ //throw ex;
+ }
+ }
+ }
+
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
- return startServiceAsUser(service, mUser);
+ return startServiceCommon(service, mUser);
}
@Override
public boolean stopService(Intent service) {
warnIfCallingFromSystemProcess();
- return stopServiceAsUser(service, mUser);
+ return stopServiceCommon(service, mUser);
}
@Override
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
+ return startServiceCommon(service, user);
+ }
+
+ private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
- if (service.getComponent() == null && service.getPackage() == null) {
- if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.KITKAT) {
- IllegalArgumentException ex = new IllegalArgumentException(
- "Service Intent must be explicit: " + service);
- Log.e(TAG, "This will become an error", ex);
- //throw ex;
- }
- }
+ validateServiceIntent(service);
service.prepareToLeaveProcess();
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
@@ -1507,15 +1517,12 @@
@Override
public boolean stopServiceAsUser(Intent service, UserHandle user) {
+ return stopServiceCommon(service, user);
+ }
+
+ private boolean stopServiceCommon(Intent service, UserHandle user) {
try {
- if (service.getComponent() == null && service.getPackage() == null) {
- if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.KITKAT) {
- IllegalArgumentException ex = new IllegalArgumentException(
- "Service Intent must be explicit: " + service);
- Log.e(TAG, "This will become an error", ex);
- //throw ex;
- }
- }
+ validateServiceIntent(service);
service.prepareToLeaveProcess();
int res = ActivityManagerNative.getDefault().stopService(
mMainThread.getApplicationThread(), service,
@@ -1534,13 +1541,18 @@
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
- return bindServiceAsUser(service, conn, flags, Process.myUserHandle());
+ return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
+ return bindServiceCommon(service, conn, flags, user);
+ }
+
+ private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
+ UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
@@ -1551,14 +1563,7 @@
} else {
throw new RuntimeException("Not supported in system context");
}
- if (service.getComponent() == null && service.getPackage() == null) {
- if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.KITKAT) {
- IllegalArgumentException ex = new IllegalArgumentException(
- "Service Intent must be explicit: " + service);
- Log.e(TAG, "This will become an error", ex);
- //throw ex;
- }
- }
+ validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 02ccaa5..50401bd 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1657,9 +1657,8 @@
* Request that a given application service be started. The Intent
* should contain either contain the complete class name of a specific service
* implementation to start or a specific package name to target. If the
- * Intent is less specified, it will either throw an {@link IllegalArgumentException}
- * (if the caller targets {@link android.os.Build.VERSION_CODES#KITKAT} or later),
- * or which of multiple matching services it finds and uses will be undefined. If this service
+ * Intent is less specified, it log a warning about this and which of the
+ * multiple matching services it finds and uses will be undefined. If this service
* is not already running, it will be instantiated and started (creating a
* process for it if needed); if it is running then it remains running.
*
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index 4054a92..02a73d66 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -25,6 +25,8 @@
* Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
*/
- oneway void notifyCallback(int msgType, int ext1, int ext2);
- oneway void onResultReceived(int frameId, in CameraMetadataNative result);
+ oneway void onCameraError(int errorCode);
+ oneway void onCameraIdle();
+ oneway void onCaptureStarted(int requestId, long timestamp);
+ oneway void onResultReceived(int requestId, in CameraMetadataNative result);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 70a6f44..463063c 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -183,13 +183,8 @@
// Need a valid handler, or current thread needs to have a looper, if
// listener is valid
- if (handler == null && listener != null) {
- Looper looper = Looper.myLooper();
- if (looper == null) {
- throw new IllegalArgumentException(
- "No handler given, and current thread has no looper!");
- }
- handler = new Handler(looper);
+ if (listener != null) {
+ handler = checkHandler(handler);
}
synchronized (mLock) {
@@ -271,12 +266,16 @@
// impossible
return;
}
- }
+ }
}
@Override
public void setDeviceListener(StateListener listener, Handler handler) {
synchronized (mLock) {
+ if (listener != null) {
+ handler = checkHandler(handler);
+ }
+
mDeviceListener = listener;
mDeviceHandler = handler;
}
@@ -365,21 +364,113 @@
}
- // TODO: unit tests
public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
+ //
+ // Constants below need to be kept up-to-date with
+ // frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
+ //
+
+ //
+ // Error codes for onCameraError
+ //
+
+ /**
+ * Camera has been disconnected
+ */
+ static final int ERROR_CAMERA_DISCONNECTED = 0;
+
+ /**
+ * Camera has encountered a device-level error
+ * Matches CameraDevice.StateListener#ERROR_CAMERA_DEVICE
+ */
+ static final int ERROR_CAMERA_DEVICE = 1;
+
+ /**
+ * Camera has encountered a service-level error
+ * Matches CameraDevice.StateListener#ERROR_CAMERA_SERVICE
+ */
+ static final int ERROR_CAMERA_SERVICE = 2;
+
@Override
public IBinder asBinder() {
return this;
}
- // TODO: consider rename to onMessageReceived
@Override
- public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
- if (DEBUG) {
- Log.d(TAG, "Got message " + msgType + " ext1: " + ext1 + " , ext2: " + ext2);
+ public void onCameraError(final int errorCode) {
+ synchronized (mLock) {
+ if (CameraDevice.this.mDeviceListener == null) return;
+ final StateListener listener = CameraDevice.this.mDeviceListener;
+ Runnable r = null;
+ switch (errorCode) {
+ case ERROR_CAMERA_DISCONNECTED:
+ r = new Runnable() {
+ public void run() {
+ listener.onDisconnected(CameraDevice.this);
+ }
+ };
+ break;
+ case ERROR_CAMERA_DEVICE:
+ case ERROR_CAMERA_SERVICE:
+ r = new Runnable() {
+ public void run() {
+ listener.onError(CameraDevice.this, errorCode);
+ }
+ };
+ break;
+ default:
+ Log.e(TAG, "Unknown error from camera device: " + errorCode);
+ }
+ if (r != null) {
+ CameraDevice.this.mDeviceHandler.post(r);
+ }
}
- // TODO implement rest
+ }
+
+ @Override
+ public void onCameraIdle() {
+ if (DEBUG) {
+ Log.d(TAG, "Camera now idle");
+ }
+ synchronized (mLock) {
+ if (CameraDevice.this.mDeviceListener == null) return;
+ final StateListener listener = CameraDevice.this.mDeviceListener;
+ Runnable r = new Runnable() {
+ public void run() {
+ listener.onIdle(CameraDevice.this);
+ }
+ };
+ CameraDevice.this.mDeviceHandler.post(r);
+ }
+ }
+
+ @Override
+ public void onCaptureStarted(int requestId, final long timestamp) {
+ if (DEBUG) {
+ Log.d(TAG, "Capture started for id " + requestId);
+ }
+ final CaptureListenerHolder holder;
+
+ // Get the listener for this frame ID, if there is one
+ synchronized (mLock) {
+ holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
+ }
+
+ if (holder == null) {
+ return;
+ }
+
+ // Dispatch capture start notice
+ holder.getHandler().post(
+ new Runnable() {
+ public void run() {
+ holder.getListener().onCaptureStarted(
+ CameraDevice.this,
+ holder.getRequest(),
+ timestamp);
+ }
+ });
}
@Override
@@ -429,6 +520,22 @@
}
+ /**
+ * Default handler management. If handler is null, get the current thread's
+ * Looper to create a Handler with. If no looper exists, throw exception.
+ */
+ private Handler checkHandler(Handler handler) {
+ if (handler == null) {
+ Looper looper = Looper.myLooper();
+ if (looper == null) {
+ throw new IllegalArgumentException(
+ "No handler given, and current thread has no looper!");
+ }
+ handler = new Handler(looper);
+ }
+ return handler;
+ }
+
private void checkIfCameraClosed() {
if (mRemoteDevice == null) {
throw new IllegalStateException("CameraDevice was already closed");
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 6d7b03e..6d04bf8 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -652,7 +652,6 @@
* We use a class initializer to allow the native code to cache some field offsets
*/
static {
- System.loadLibrary("media_jni");
nativeClassInit();
Log.v(TAG, "Shall register metadata marshalers");
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 88eb280..114a1ea 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -438,17 +438,28 @@
public static final int JELLY_BEAN_MR2 = 18;
/**
- * Android X.X: KitKat, another tasty treat.
+ * Android 4.4: KitKat, another tasty treat.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
- * <li>It is no longer allowed to use implicit intents with
- * {@link android.content.Context#startService} or
- * {@link android.content.Context#bindService}.
+ * <li> The default result of {android.preference.PreferenceActivity#isValidFragment
+ * PreferenceActivity.isValueFragment} becomes false instead of true.</li>
+ * <li> In {@link android.webkit.WebView}, apps targeting earlier versions will have
+ * JS URLs evaluated directly and any result of the evaluation will not replace
+ * the current page content. Apps targetting KITKAT or later that load a JS URL will
+ * have the result of that URL replace the content of the current page</li>
+ * <li> {@link android.app.AlarmManager#set AlarmManager.set} becomes interpreted as
+ * an inexact value, to give the system more flexibility in scheduling alarms.</li>
+ * <li> {@link android.content.Context#getSharedPreferences(String, int)
+ * Context.getSharedPreferences} no longer allows a null name.</li>
+ * <li> {@link android.widget.RelativeLayout} changes to compute wrapped content
+ * margins correctly.</li>
+ * <li> {@link android.app.ActionBar}'s window content overlay is allowed to be
+ * drawn.</li>
* </ul>
*/
- public static final int KITKAT = CUR_DEVELOPMENT;
+ public static final int KITKAT = 19;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index f47ac4e..5a919fb 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -30,7 +30,8 @@
*
*/
public final class Bundle implements Parcelable, Cloneable {
- private static final String LOG_TAG = "Bundle";
+ private static final String TAG = "Bundle";
+ static final boolean DEBUG = false;
public static final Bundle EMPTY;
static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
@@ -157,7 +158,7 @@
unparcel();
int size = mMap.size();
if (size > 1) {
- Log.w(LOG_TAG, "getPairValue() used on Bundle with multiple pairs.");
+ Log.w(TAG, "getPairValue() used on Bundle with multiple pairs.");
}
if (size == 0) {
return null;
@@ -210,10 +211,14 @@
*/
/* package */ synchronized void unparcel() {
if (mParcelledData == null) {
+ if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ + ": no parcelled data");
return;
}
int N = mParcelledData.readInt();
+ if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ + ": reading " + N + " maps");
if (N < 0) {
return;
}
@@ -226,6 +231,8 @@
mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
mParcelledData.recycle();
mParcelledData = null;
+ if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ + " final map: " + mMap);
}
/**
@@ -794,6 +801,8 @@
*/
public boolean getBoolean(String key) {
unparcel();
+ if (DEBUG) Log.d(TAG, "Getting boolean in "
+ + Integer.toHexString(System.identityHashCode(this)));
return getBoolean(key, false);
}
@@ -810,8 +819,8 @@
sb.append(". The default value ");
sb.append(defaultValue);
sb.append(" was returned.");
- Log.w(LOG_TAG, sb.toString());
- Log.w(LOG_TAG, "Attempt to cast generated internal exception:", e);
+ Log.w(TAG, sb.toString());
+ Log.w(TAG, "Attempt to cast generated internal exception:", e);
}
private void typeWarning(String key, Object value, String className,
@@ -1648,18 +1657,19 @@
parcel.writeInt(BUNDLE_MAGIC);
parcel.appendFrom(mParcelledData, 0, length);
} else {
+ int lengthPos = parcel.dataPosition();
parcel.writeInt(-1); // dummy, will hold length
parcel.writeInt(BUNDLE_MAGIC);
- int oldPos = parcel.dataPosition();
+ int startPos = parcel.dataPosition();
parcel.writeArrayMapInternal(mMap);
- int newPos = parcel.dataPosition();
+ int endPos = parcel.dataPosition();
// Backpatch length
- parcel.setDataPosition(oldPos - 8);
- int length = newPos - oldPos;
+ parcel.setDataPosition(lengthPos);
+ int length = endPos - startPos;
parcel.writeInt(length);
- parcel.setDataPosition(newPos);
+ parcel.setDataPosition(endPos);
}
} finally {
parcel.restoreAllowFds(oldAllowFds);
@@ -1694,24 +1704,13 @@
Parcel p = Parcel.obtain();
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
+ if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))
+ + ": " + length + " bundle bytes starting at " + offset);
p.setDataPosition(0);
- if (mMap != null) {
- // It is not allowed to have a Bundle with both a map and a parcel, so if we
- // already have a map then we need to immediately unparcel into it. This also
- // lets us know we need to go through the slow path of unparceling, since the
- // map may already contains some data so the two need to be merged.
- if (mFdsKnown) {
- mHasFds |= p.hasFileDescriptors();
- }
- int N = p.readInt();
- p.readArrayMapSafelyInternal(mMap, N, mClassLoader);
- p.recycle();
- } else {
- mParcelledData = p;
- mHasFds = p.hasFileDescriptors();
- mFdsKnown = true;
- }
+ mParcelledData = p;
+ mHasFds = p.hasFileDescriptors();
+ mFdsKnown = true;
}
@Override
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index ea9fd06..974bf8d 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -124,6 +124,9 @@
/** The shared clean pages used by dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikSharedClean;
+ /** The dirty dalvik pages that have been swapped out. */
+ /** @hide We may want to expose this, eventually. */
+ public int dalvikSwappedOut;
/** The proportional set size for the native heap. */
public int nativePss;
@@ -140,6 +143,9 @@
/** The shared clean pages used by the native heap. */
/** @hide We may want to expose this, eventually. */
public int nativeSharedClean;
+ /** The dirty native pages that have been swapped out. */
+ /** @hide We may want to expose this, eventually. */
+ public int nativeSwappedOut;
/** The proportional set size for everything else. */
public int otherPss;
@@ -156,6 +162,9 @@
/** The shared clean pages used by everything else. */
/** @hide We may want to expose this, eventually. */
public int otherSharedClean;
+ /** The dirty pages used by anyting else that have been swapped out. */
+ /** @hide We may want to expose this, eventually. */
+ public int otherSwappedOut;
/** @hide */
public static final int NUM_OTHER_STATS = 16;
@@ -164,7 +173,7 @@
public static final int NUM_DVK_STATS = 5;
/** @hide */
- public static final int NUM_CATEGORIES = 6;
+ public static final int NUM_CATEGORIES = 7;
/** @hide */
public static final int offsetPss = 0;
@@ -178,7 +187,8 @@
public static final int offsetPrivateClean = 4;
/** @hide */
public static final int offsetSharedClean = 5;
-
+ /** @hide */
+ public static final int offsetSwappedOut = 6;
private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
@@ -236,6 +246,14 @@
return dalvikSharedClean + nativeSharedClean + otherSharedClean;
}
+ /**
+ * Return total swapped out memory in kB.
+ * @hide
+ */
+ public int getTotalSwappedOut() {
+ return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut;
+ }
+
/** @hide */
public int getOtherPss(int which) {
return otherStats[which*NUM_CATEGORIES + offsetPss];
@@ -263,13 +281,17 @@
return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
}
-
/** @hide */
public int getOtherSharedClean(int which) {
return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
}
/** @hide */
+ public int getOtherSwappedOut(int which) {
+ return otherStats[which*NUM_CATEGORIES + offsetSwappedOut];
+ }
+
+ /** @hide */
public static String getOtherLabel(int which) {
switch (which) {
case 0: return "Dalvik Other";
@@ -287,7 +309,7 @@
case 12: return "Other mmap";
case 13: return "Graphics";
case 14: return "GL";
- case 15: return "Other memtrack";
+ case 15: return "Memtrack";
case 16: return ".Heap";
case 17: return ".LOS";
case 18: return ".LinearAlloc";
@@ -308,18 +330,21 @@
dest.writeInt(dalvikSharedDirty);
dest.writeInt(dalvikPrivateClean);
dest.writeInt(dalvikSharedClean);
+ dest.writeInt(dalvikSwappedOut);
dest.writeInt(nativePss);
dest.writeInt(nativeSwappablePss);
dest.writeInt(nativePrivateDirty);
dest.writeInt(nativeSharedDirty);
dest.writeInt(nativePrivateClean);
dest.writeInt(nativeSharedClean);
+ dest.writeInt(nativeSwappedOut);
dest.writeInt(otherPss);
dest.writeInt(otherSwappablePss);
dest.writeInt(otherPrivateDirty);
dest.writeInt(otherSharedDirty);
dest.writeInt(otherPrivateClean);
dest.writeInt(otherSharedClean);
+ dest.writeInt(otherSwappedOut);
dest.writeIntArray(otherStats);
}
@@ -330,18 +355,21 @@
dalvikSharedDirty = source.readInt();
dalvikPrivateClean = source.readInt();
dalvikSharedClean = source.readInt();
+ dalvikSwappedOut = source.readInt();
nativePss = source.readInt();
nativeSwappablePss = source.readInt();
nativePrivateDirty = source.readInt();
nativeSharedDirty = source.readInt();
nativePrivateClean = source.readInt();
nativeSharedClean = source.readInt();
+ nativeSwappedOut = source.readInt();
otherPss = source.readInt();
otherSwappablePss = source.readInt();
otherPrivateDirty = source.readInt();
otherSharedDirty = source.readInt();
otherPrivateClean = source.readInt();
otherSharedClean = source.readInt();
+ otherSwappedOut = source.readInt();
otherStats = source.createIntArray();
}
@@ -1582,6 +1610,22 @@
}
/**
+ * Return a string consisting of methods and locations at multiple call stack levels.
+ * @param depth the number of levels to return, starting with the immediate caller.
+ * @return a string describing the call stack.
+ * {@hide}
+ */
+ public static String getCallers(final int start, int depth) {
+ final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+ StringBuffer sb = new StringBuffer();
+ depth += start;
+ for (int i = start; i < depth; i++) {
+ sb.append(getCaller(callStack, i)).append(" ");
+ }
+ return sb.toString();
+ }
+
+ /**
* Like {@link #getCallers(int)}, but each location is append to the string
* as a new line with <var>linePrefix</var> in front of it.
* @param depth the number of levels to return, starting with the immediate caller.
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 5f3a81c..02b1998 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1610,6 +1610,7 @@
public final Bundle readBundle(ClassLoader loader) {
int length = readInt();
if (length < 0) {
+ if (Bundle.DEBUG) Log.d(TAG, "null bundle: length=" + length);
return null;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3769e1e..631a38f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2407,6 +2407,15 @@
public static final String POINTER_SPEED = "pointer_speed";
/**
+ * I am the lolrus.
+ * <p>
+ * Nonzero values indicate that the user has a bukkit.
+ * Backward-compatible with <code>PrefGetPreference(prefAllowEasterEggs)</code>.
+ * @hide
+ */
+ public static final String EGG_MODE = "egg_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/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index fa534cc..df1d4cd 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -292,6 +292,7 @@
for (int i=0; i<N; i++) {
array[i] = null;
}
+ mSize = 0;
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 06f00f7..f763d19 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2121,6 +2121,12 @@
public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
/**
+ * The view is not important for accessibility, nor are any of its
+ * descendant views.
+ */
+ public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
+
+ /**
* The default whether the view is important for accessibility.
*/
static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
@@ -2130,14 +2136,15 @@
* whether a view is important for accessibility.
*/
static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
- | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
+ | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
+ | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
<< PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
/**
* Shift for the bits in {@link #mPrivateFlags2} related to the
* "accessibilityLiveRegion" attribute.
*/
- static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 22;
+ static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
/**
* Live region mode specifying that accessibility services should not
@@ -6999,12 +7006,15 @@
*
* @see #IMPORTANT_FOR_ACCESSIBILITY_YES
* @see #IMPORTANT_FOR_ACCESSIBILITY_NO
+ * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
* @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
*/
@ViewDebug.ExportedProperty(category = "accessibility", mapping = {
@ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
@ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
- @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
+ to = "noHideDescendants")
})
public int getImportantForAccessibility() {
return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
@@ -7074,6 +7084,7 @@
*
* @see #IMPORTANT_FOR_ACCESSIBILITY_YES
* @see #IMPORTANT_FOR_ACCESSIBILITY_NO
+ * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
* @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
*/
public void setImportantForAccessibility(int mode) {
@@ -7101,19 +7112,24 @@
public boolean isImportantForAccessibility() {
final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
>> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
- switch (mode) {
- case IMPORTANT_FOR_ACCESSIBILITY_YES:
- return true;
- case IMPORTANT_FOR_ACCESSIBILITY_NO:
- return false;
- case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
- return isActionableForAccessibility() || hasListenersForAccessibility()
- || getAccessibilityNodeProvider() != null
- || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
- default:
- throw new IllegalArgumentException("Unknow important for accessibility mode: "
- + mode);
+ if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
+ || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
+ return false;
}
+
+ // Check parent mode to ensure we're not hidden.
+ ViewParent parent = mParent;
+ while (parent instanceof View) {
+ if (((View) parent).getImportantForAccessibility()
+ == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
+ return false;
+ }
+ parent = parent.getParent();
+ }
+
+ return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
+ || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
+ || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
}
/**
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index 276bcae..13aa43f 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -59,8 +59,10 @@
private static CookieSyncManager sRef;
- private CookieSyncManager(Context context) {
- super(context, "CookieSyncManager");
+ private static boolean sGetInstanceAllowed = false;
+
+ private CookieSyncManager() {
+ super("CookieSyncManager");
}
/**
@@ -71,7 +73,10 @@
* @return CookieSyncManager
*/
public static synchronized CookieSyncManager getInstance() {
- checkInstanceIsCreated();
+ checkInstanceIsAllowed();
+ if (sRef == null) {
+ sRef = new CookieSyncManager();
+ }
return sRef;
}
@@ -80,16 +85,13 @@
* @param context
* @return CookieSyncManager
*/
- public static synchronized CookieSyncManager createInstance(
- Context context) {
+ public static synchronized CookieSyncManager createInstance(Context context) {
if (context == null) {
throw new IllegalArgumentException("Invalid context argument");
}
- if (sRef == null) {
- sRef = new CookieSyncManager(context);
- }
- return sRef;
+ setGetInstanceIsAllowed();
+ return getInstance();
}
protected void syncFromRamToFlash() {
@@ -110,8 +112,15 @@
}
}
- private static void checkInstanceIsCreated() {
- if (sRef == null) {
+ static void setGetInstanceIsAllowed() {
+ sGetInstanceAllowed = true;
+ }
+
+ private static void checkInstanceIsAllowed() {
+ // Prior to Android KK, calling createInstance() or constructing a WebView is
+ // a hard pre-condition for calling getInstance(). We retain that contract to aid
+ // developers targeting a range of SDK levels.
+ if (!sGetInstanceAllowed) {
throw new IllegalStateException(
"CookieSyncManager::createInstance() needs to be called "
+ "before CookieSyncManager::getInstance()");
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index d3ec603..c600a7e 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -36,7 +36,7 @@
private String mThreadName;
// handler of the sync thread
protected Handler mHandler;
- // database for the persistent storage
+ // database for the persistent storage. Always null.
protected WebViewDatabase mDataBase;
// Ref count for calls to start/stop sync
private int mStartSyncRefCount;
@@ -60,16 +60,15 @@
}
protected WebSyncManager(Context context, String name) {
+ this(name);
+ }
+
+ /** @hide */
+ WebSyncManager(String name) {
mThreadName = name;
- if (context != null) {
- mDataBase = WebViewDatabase.getInstance(context);
- mSyncThread = new Thread(this);
- mSyncThread.setName(mThreadName);
- mSyncThread.start();
- } else {
- throw new IllegalStateException(
- "WebSyncManager can't be created without context");
- }
+ mSyncThread = new Thread(this);
+ mSyncThread.setName(mThreadName);
+ mSyncThread.start();
}
protected Object clone() throws CloneNotSupportedException {
@@ -82,7 +81,7 @@
mHandler = new SyncHandler();
onSyncInit();
// lower the priority after onSyncInit() is done
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Message msg = mHandler.obtainMessage(SYNC_MESSAGE);
mHandler.sendMessageDelayed(msg, SYNC_LATER_INTERVAL);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 90cc72e..2cbe0e2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -506,8 +506,8 @@
ensureProviderCreated();
mProvider.init(javaScriptInterfaces, privateBrowsing);
- // Post condition of creating a webview is the CookieSyncManager instance exists.
- CookieSyncManager.createInstance(getContext());
+ // Post condition of creating a webview is the CookieSyncManager.getInstance() is allowed.
+ CookieSyncManager.setGetInstanceIsAllowed();
}
/**
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 76b8579..43bd735 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
+import android.provider.Settings;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -151,6 +152,13 @@
logo.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
+ if (Settings.System.getLong(getContentResolver(), Settings.System.EGG_MODE, 0)
+ == 0) {
+ // For posterity: the moment this user unlocked the easter egg
+ Settings.System.putLong(getContentResolver(),
+ Settings.System.EGG_MODE,
+ System.currentTimeMillis());
+ }
try {
startActivity(new Intent(Intent.ACTION_MAIN)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -158,7 +166,7 @@
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
.addCategory("com.android.internal.category.PLATLOGO"));
} catch (ActivityNotFoundException ex) {
- android.util.Log.e("PlatLogoActivity", "Couldn't find a piece of pie.");
+ android.util.Log.e("PlatLogoActivity", "Couldn't catch a break.");
}
finish();
return true;
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 62f057f..054ee4f6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -80,6 +80,7 @@
jfieldID sharedDirty_field;
jfieldID privateClean_field;
jfieldID sharedClean_field;
+ jfieldID swappedOut_field;
};
struct stat_field_names {
@@ -89,14 +90,18 @@
const char* sharedDirty_name;
const char* privateClean_name;
const char* sharedClean_name;
+ const char* swappedOut_name;
};
static stat_fields stat_fields[_NUM_CORE_HEAP];
static stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
- { "otherPss", "otherSwappablePss", "otherPrivateDirty", "otherSharedDirty", "otherPrivateClean", "otherSharedClean" },
- { "dalvikPss", "dalvikSwappablePss", "dalvikPrivateDirty", "dalvikSharedDirty", "dalvikPrivateClean", "dalvikSharedClean" },
- { "nativePss", "nativeSwappablePss", "nativePrivateDirty", "nativeSharedDirty", "nativePrivateClean", "nativeSharedClean" }
+ { "otherPss", "otherSwappablePss", "otherPrivateDirty", "otherSharedDirty",
+ "otherPrivateClean", "otherSharedClean", "otherSwappedOut" },
+ { "dalvikPss", "dalvikSwappablePss", "dalvikPrivateDirty", "dalvikSharedDirty",
+ "dalvikPrivateClean", "dalvikSharedClean", "dalvikSwappedOut" },
+ { "nativePss", "nativeSwappablePss", "nativePrivateDirty", "nativeSharedDirty",
+ "nativePrivateClean", "nativeSharedClean", "nativeSwappedOut" }
};
jfieldID otherStats_field;
@@ -110,6 +115,7 @@
int sharedDirty;
int privateClean;
int sharedClean;
+ int swappedOut;
};
#define BINDER_STATS "/proc/binder/stats"
@@ -219,6 +225,7 @@
float sharing_proportion = 0.0;
unsigned shared_clean = 0, shared_dirty = 0;
unsigned private_clean = 0, private_dirty = 0;
+ unsigned swapped_out = 0;
bool is_swappable = false;
unsigned referenced = 0;
unsigned temp;
@@ -333,28 +340,36 @@
//ALOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
// isSqliteHeap, line);
+ shared_clean = 0;
+ shared_dirty = 0;
+ private_clean = 0;
+ private_dirty = 0;
+ swapped_out = 0;
+
while (true) {
if (fgets(line, 1024, fp) == 0) {
done = true;
break;
}
- if (sscanf(line, "Size: %d kB", &temp) == 1) {
+ if (line[0] == 'S' && sscanf(line, "Size: %d kB", &temp) == 1) {
size = temp;
- } else if (sscanf(line, "Rss: %d kB", &temp) == 1) {
+ } else if (line[0] == 'R' && sscanf(line, "Rss: %d kB", &temp) == 1) {
resident = temp;
- } else if (sscanf(line, "Pss: %d kB", &temp) == 1) {
+ } else if (line[0] == 'P' && sscanf(line, "Pss: %d kB", &temp) == 1) {
pss = temp;
- } else if (sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
+ } else if (line[0] == 'S' && sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
shared_clean = temp;
- } else if (sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
+ } else if (line[0] == 'S' && sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
shared_dirty = temp;
- } else if (sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
+ } else if (line[0] == 'P' && sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
private_clean = temp;
- } else if (sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
+ } else if (line[0] == 'P' && sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
private_dirty = temp;
- } else if (sscanf(line, "Referenced: %d kB", &temp) == 1) {
+ } else if (line[0] == 'R' && sscanf(line, "Referenced: %d kB", &temp) == 1) {
referenced = temp;
+ } else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
+ swapped_out = temp;
} else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') {
// looks like a new mapping
// example: "10000000-10001000 ---p 10000000 00:00 0"
@@ -366,7 +381,8 @@
if (is_swappable && (pss > 0)) {
sharing_proportion = 0.0;
if ((shared_clean > 0) || (shared_dirty > 0)) {
- sharing_proportion = (pss - private_clean - private_dirty)/(shared_clean+shared_dirty);
+ sharing_proportion = (pss - private_clean
+ - private_dirty)/(shared_clean+shared_dirty);
}
swappable_pss = (sharing_proportion*shared_clean) + private_clean;
} else
@@ -378,6 +394,7 @@
stats[whichHeap].sharedDirty += shared_dirty;
stats[whichHeap].privateClean += private_clean;
stats[whichHeap].sharedClean += shared_clean;
+ stats[whichHeap].swappedOut += swapped_out;
if (whichHeap == HEAP_DALVIK || whichHeap == HEAP_DALVIK_OTHER) {
stats[subHeap].pss += pss;
stats[subHeap].swappablePss += swappable_pss;
@@ -385,6 +402,7 @@
stats[subHeap].sharedDirty += shared_dirty;
stats[subHeap].privateClean += private_clean;
stats[subHeap].sharedClean += shared_clean;
+ stats[subHeap].swappedOut += swapped_out;
}
}
}
@@ -428,6 +446,7 @@
stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty;
stats[HEAP_UNKNOWN].privateClean += stats[i].privateClean;
stats[HEAP_UNKNOWN].sharedClean += stats[i].sharedClean;
+ stats[HEAP_UNKNOWN].swappedOut += stats[i].swappedOut;
}
for (int i=0; i<_NUM_CORE_HEAP; i++) {
@@ -437,6 +456,7 @@
env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
env->SetIntField(object, stat_fields[i].privateClean_field, stats[i].privateClean);
env->SetIntField(object, stat_fields[i].sharedClean_field, stats[i].sharedClean);
+ env->SetIntField(object, stat_fields[i].swappedOut_field, stats[i].swappedOut);
}
@@ -455,6 +475,7 @@
otherArray[j++] = stats[i].sharedDirty;
otherArray[j++] = stats[i].privateClean;
otherArray[j++] = stats[i].sharedClean;
+ otherArray[j++] = stats[i].swappedOut;
}
env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0);
@@ -971,6 +992,8 @@
env->GetFieldID(clazz, stat_field_names[i].privateClean_name, "I");
stat_fields[i].sharedClean_field =
env->GetFieldID(clazz, stat_field_names[i].sharedClean_name, "I");
+ stat_fields[i].swappedOut_field =
+ env->GetFieldID(clazz, stat_field_names[i].swappedOut_name, "I");
}
return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 275afb8..c3dc4ff 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2182,6 +2182,9 @@
<enum name="yes" value="1" />
<!-- The view is not important for accessibility. -->
<enum name="no" value="2" />
+ <!-- The view is not important for accessibility, nor are any of its descendant
+ views. -->
+ <enum name="noHideDescendants" value="4" />
</attr>
<!-- Indicates to accessibility services whether the user should be notified when
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ef7f2b7..431fe82 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2054,29 +2054,29 @@
<public type="style" name="Theme.DeviceDefault.Light.NoActionBar.Overscan" id="0x010301e0" />
<!-- ===============================================================
- Resources added in version 19 of the platform
+ Resources added in version 19 of the platform (KitKat)
=============================================================== -->
<eat-comment />
- <public type="attr" name="keySet" />
- <public type="attr" name="targetId" />
- <public type="attr" name="fromScene" />
- <public type="attr" name="toScene" />
- <public type="attr" name="transition" />
- <public type="attr" name="transitionOrdering" />
- <public type="attr" name="fadingMode" />
- <public type="attr" name="startDelay" />
- <public type="attr" name="ssp" />
- <public type="attr" name="sspPrefix" />
- <public type="attr" name="sspPattern" />
- <public type="attr" name="addPrintersActivity" />
- <public type="attr" name="vendor" />
- <public type="attr" name="category" />
- <public type="attr" name="isAsciiCapable" />
- <public type="attr" name="autoMirrored" />
- <public type="attr" name="supportsSwitchingToNextInputMethod" />
- <public type="attr" name="requireDeviceUnlock" />
- <public type="attr" name="apduServiceBanner" />
- <public type="attr" name="accessibilityLiveRegion" />
+ <public type="attr" name="keySet" id="0x010103db" />
+ <public type="attr" name="targetId" id="0x010103dc" />
+ <public type="attr" name="fromScene" id="0x010103dd" />
+ <public type="attr" name="toScene" id="0x010103de" />
+ <public type="attr" name="transition" id="0x010103df" />
+ <public type="attr" name="transitionOrdering" id="0x010103e0" />
+ <public type="attr" name="fadingMode" id="0x010103e1" />
+ <public type="attr" name="startDelay" id="0x010103e2" />
+ <public type="attr" name="ssp" id="0x010103e3" />
+ <public type="attr" name="sspPrefix" id="0x010103e4" />
+ <public type="attr" name="sspPattern" id="0x010103e5" />
+ <public type="attr" name="addPrintersActivity" id="0x010103e6" />
+ <public type="attr" name="vendor" id="0x010103e7" />
+ <public type="attr" name="category" id="0x010103e8" />
+ <public type="attr" name="isAsciiCapable" id="0x010103e9" />
+ <public type="attr" name="autoMirrored" id="0x010103ea" />
+ <public type="attr" name="supportsSwitchingToNextInputMethod" id="0x010103eb" />
+ <public type="attr" name="requireDeviceUnlock" id="0x010103ec" />
+ <public type="attr" name="apduServiceBanner" id="0x010103ed" />
+ <public type="attr" name="accessibilityLiveRegion" id="0x010103ee" />
</resources>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 1b7faec..d157478 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -152,11 +152,20 @@
static class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
@Override
- public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+ public void onCameraError(int errorCode) {
}
@Override
- public void onResultReceived(int frameId, CameraMetadataNative result) throws RemoteException {
+ public void onCameraIdle() {
+ }
+
+ @Override
+ public void onCaptureStarted(int requestId, long timestamp) {
+ }
+
+ @Override
+ public void onResultReceived(int frameId, CameraMetadataNative result)
+ throws RemoteException {
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 13ce52e..43ebef4 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -30,6 +30,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
@@ -40,6 +41,7 @@
import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;
import org.mockito.ArgumentMatcher;
+import org.mockito.ArgumentCaptor;
import static org.mockito.Mockito.*;
public class CameraDeviceBinderTest extends AndroidTestCase {
@@ -48,6 +50,12 @@
private static int NUM_CALLBACKS_CHECKED = 10;
// Wait for capture result timeout value: 1500ms
private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500;
+ // Wait for flush timeout value: 1000ms
+ private final static int WAIT_FOR_FLUSH_TIMEOUT_MS = 1000;
+ // Wait for idle timeout value: 2000ms
+ private final static int WAIT_FOR_IDLE_TIMEOUT_MS = 2000;
+ // Wait while camera device starts working on requests
+ private final static int WAIT_FOR_WORK_MS = 300;
// Default size is VGA, which is mandatory camera supported image size by CDD.
private static final int DEFAULT_IMAGE_WIDTH = 640;
private static final int DEFAULT_IMAGE_HEIGHT = 480;
@@ -77,11 +85,19 @@
public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
@Override
- public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+ public void onCameraError(int errorCode) {
}
@Override
- public void onResultReceived(int frameId, CameraMetadataNative result) throws RemoteException {
+ public void onCameraIdle() {
+ }
+
+ @Override
+ public void onCaptureStarted(int requestId, long timestamp) {
+ }
+
+ @Override
+ public void onResultReceived(int frameId, CameraMetadataNative result) {
}
}
@@ -90,7 +106,7 @@
public boolean matches(Object obj) {
return !((CameraMetadataNative) obj).isEmpty();
}
- }
+ }
private void createDefaultSurface() {
mImageReader =
@@ -346,6 +362,60 @@
}
@SmallTest
+ public void testCaptureStartedCallbacks() throws Exception {
+ CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
+
+ ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
+
+ // Test both single request and streaming request.
+ int requestId1 = submitCameraRequest(request, /* streaming */false);
+ verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
+ eq(requestId1),
+ anyLong());
+
+ int streamingId = submitCameraRequest(request, /* streaming */true);
+ verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
+ .onCaptureStarted(
+ eq(streamingId),
+ timestamps.capture());
+
+ long timestamp = 0; // All timestamps should be larger than 0.
+ for (Long nextTimestamp : timestamps.getAllValues()) {
+ Log.v(TAG, "next t: " + nextTimestamp + " current t: " + timestamp);
+ assertTrue("Captures are out of order", timestamp < nextTimestamp);
+ timestamp = nextTimestamp;
+ }
+ }
+
+ @SmallTest
+ public void testIdleCallback() throws Exception {
+ int status;
+ CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
+
+ // Try streaming
+ int streamingId = submitCameraRequest(request, /* streaming */true);
+
+ // Wait a bit to fill up the queue
+ SystemClock.sleep(WAIT_FOR_WORK_MS);
+
+ // Cancel and make sure we eventually quiesce
+ status = mCameraUser.cancelRequest(streamingId);
+
+ verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onCameraIdle();
+
+ // Submit a few capture requests
+ int requestId1 = submitCameraRequest(request, /* streaming */false);
+ int requestId2 = submitCameraRequest(request, /* streaming */false);
+ int requestId3 = submitCameraRequest(request, /* streaming */false);
+ int requestId4 = submitCameraRequest(request, /* streaming */false);
+ int requestId5 = submitCameraRequest(request, /* streaming */false);
+
+ // And wait for more idle
+ verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onCameraIdle();
+
+ }
+
+ @SmallTest
public void testFlush() throws Exception {
int status;
@@ -367,10 +437,24 @@
int requestId4 = submitCameraRequest(request, /* streaming */false);
int requestId5 = submitCameraRequest(request, /* streaming */false);
- // Then flush
+ // Then flush and wait for idle
status = mCameraUser.flush();
assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onCameraIdle();
+
+ // Now a streaming request
+ int streamingId = submitCameraRequest(request, /* streaming */true);
+
+ // Wait a bit to fill up the queue
+ SystemClock.sleep(WAIT_FOR_WORK_MS);
+
+ // Then flush and wait for the idle callback
+ status = mCameraUser.flush();
+ assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+
+ verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onCameraIdle();
+
// TODO: When errors are hooked up, count that errors + successful
// requests equal to 5.
}
diff --git a/packages/Keyguard/res/drawable-hdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-hdpi/ic_alarm_small.png
new file mode 100644
index 0000000..3819029
--- /dev/null
+++ b/packages/Keyguard/res/drawable-hdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_alarm.png b/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_alarm.png
deleted file mode 100644
index d7a8cfc..0000000
--- a/packages/Keyguard/res/drawable-hdpi/ic_lockscreen_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-mdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-mdpi/ic_alarm_small.png
new file mode 100644
index 0000000..2aeedaf
--- /dev/null
+++ b/packages/Keyguard/res/drawable-mdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_alarm.png b/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_alarm.png
deleted file mode 100644
index 330ade1..0000000
--- a/packages/Keyguard/res/drawable-mdpi/ic_lockscreen_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-sw600dp-hdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-sw600dp-hdpi/ic_alarm_small.png
new file mode 100644
index 0000000..e28b3f6
--- /dev/null
+++ b/packages/Keyguard/res/drawable-sw600dp-hdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/drawable-sw600dp-mdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-sw600dp-mdpi/ic_alarm_small.png
new file mode 100644
index 0000000..f727d01
--- /dev/null
+++ b/packages/Keyguard/res/drawable-sw600dp-mdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/drawable-sw600dp-xhdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-sw600dp-xhdpi/ic_alarm_small.png
new file mode 100644
index 0000000..d9c0623
--- /dev/null
+++ b/packages/Keyguard/res/drawable-sw600dp-xhdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/drawable-sw600dp-xxhdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-sw600dp-xxhdpi/ic_alarm_small.png
new file mode 100644
index 0000000..a36bf1f
--- /dev/null
+++ b/packages/Keyguard/res/drawable-sw600dp-xxhdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xhdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-xhdpi/ic_alarm_small.png
new file mode 100644
index 0000000..0290bdc
--- /dev/null
+++ b/packages/Keyguard/res/drawable-xhdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_alarm.png b/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_alarm.png
deleted file mode 100644
index e6cceef..0000000
--- a/packages/Keyguard/res/drawable-xhdpi/ic_lockscreen_alarm.png
+++ /dev/null
Binary files differ
diff --git a/packages/Keyguard/res/drawable-xxhdpi/ic_alarm_small.png b/packages/Keyguard/res/drawable-xxhdpi/ic_alarm_small.png
new file mode 100644
index 0000000..66968e8
--- /dev/null
+++ b/packages/Keyguard/res/drawable-xxhdpi/ic_alarm_small.png
Binary files differ
diff --git a/packages/Keyguard/res/layout-land/keyguard_status_area.xml b/packages/Keyguard/res/layout-land/keyguard_status_area.xml
deleted file mode 100644
index d450c5c..0000000
--- a/packages/Keyguard/res/layout-land/keyguard_status_area.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2009, 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.
-*/
--->
-
-<!-- This is a view that shows general status information in Keyguard. -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/keyguard_status_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end"
- android:layout_marginTop="-16dp"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end"
- android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/kg_status_date_font_size"
- android:textAllCaps="@bool/kg_use_all_caps"
- />
-
- <TextView
- android:id="@+id/alarm_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end"
- android:layout_marginTop="28dp"
- android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearance"
- android:textSize="@dimen/kg_status_line_font_size"
- android:drawablePadding="4dip"
- android:textAllCaps="@bool/kg_use_all_caps"
- />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/packages/Keyguard/res/layout-port/keyguard_status_area.xml b/packages/Keyguard/res/layout-port/keyguard_status_area.xml
deleted file mode 100644
index af0d2e8..0000000
--- a/packages/Keyguard/res/layout-port/keyguard_status_area.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2009, 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.
-*/
--->
-
-<!-- This is a view that shows general status information in Keyguard. -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/keyguard_status_area"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:orientation="vertical">
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="0dp"
- android:layout_gravity="right">
- <TextView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/kg_status_date_font_size"
- android:textAllCaps="@bool/kg_use_all_caps"
- />
-
- <TextView
- android:id="@+id/alarm_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearance"
- android:textSize="@dimen/kg_status_line_font_size"
- android:drawablePadding="4dip"
- android:textAllCaps="@bool/kg_use_all_caps"
- />
- </LinearLayout>
-
-</LinearLayout>
diff --git a/packages/Keyguard/res/layout/keyguard_status_area.xml b/packages/Keyguard/res/layout/keyguard_status_area.xml
new file mode 100644
index 0000000..d1f3873
--- /dev/null
+++ b/packages/Keyguard/res/layout/keyguard_status_area.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2013, 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.
+*/
+-->
+
+<!-- This is a view that shows general status information in Keyguard. -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center">
+ <TextClock android:id="@+id/date_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/clock_white"
+ android:format12Hour="@string/abbrev_wday_month_day_no_year"
+ android:format24Hour="@string/abbrev_wday_month_day_no_year"
+ style="@style/widget_label"
+ android:gravity="center"
+ />
+ <TextView android:id="@+id/alarm_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawablePadding="2dip"
+ android:drawableLeft="@drawable/ic_alarm_small"
+ android:drawableStart="@drawable/ic_alarm_small"
+ android:textColor="@color/clock_gray"
+ style="@style/widget_label"
+ android:layout_marginLeft="8dip"
+ android:layout_marginStart="8dip"
+ android:gravity="center"
+ android:visibility="gone"
+ />
+</LinearLayout>
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index 2304d9f..5857fc2 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -35,34 +35,26 @@
android:layout_height="match_parent"
android:gravity="center_horizontal|top"
android:contentDescription="@string/keyguard_accessibility_status">
-
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:orientation="vertical"
- android:focusable="true">
- <com.android.keyguard.ClockView
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|top"
+ android:orientation="vertical"
+ android:focusable="true">
+ <TextClock
android:id="@+id/clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/kg_status_line_font_right_margin"
- android:layout_gravity="right">
-
- <TextView android:id="@+id/clock_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="@dimen/kg_status_clock_font_size"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="#ffffffff"
- android:drawablePadding="2dip"
- />
-
- </com.android.keyguard.ClockView>
+ android:layout_gravity="center_horizontal|top"
+ android:textColor="@color/clock_white"
+ android:singleLine="true"
+ style="@style/widget_big_thin"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format"
+ android:baselineAligned="true"
+ android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
<include layout="@layout/keyguard_status_area" />
</LinearLayout>
-
</com.android.keyguard.KeyguardStatusView>
</com.android.keyguard.KeyguardWidgetFrame>
diff --git a/packages/Keyguard/res/layout/keyguard_widget_remove_drop_target.xml b/packages/Keyguard/res/layout/keyguard_widget_remove_drop_target.xml
index 294c386..58b5b27 100644
--- a/packages/Keyguard/res/layout/keyguard_widget_remove_drop_target.xml
+++ b/packages/Keyguard/res/layout/keyguard_widget_remove_drop_target.xml
@@ -26,7 +26,7 @@
android:drawablePadding="4dp"
android:text="@string/kg_reordering_delete_drop_target_text"
android:textColor="#FFF"
- android:textSize="13sp"
+ android:textSize="12dp"
android:shadowColor="#000"
android:shadowDy="1.0"
android:shadowRadius="1.0"
diff --git a/packages/Keyguard/res/values-land/dimens.xml b/packages/Keyguard/res/values-land/dimens.xml
index 64e043c..bf30332 100644
--- a/packages/Keyguard/res/values-land/dimens.xml
+++ b/packages/Keyguard/res/values-land/dimens.xml
@@ -19,17 +19,6 @@
-->
<resources>
- <!-- Default height of a key in the password keyboard for alpha -->
- <dimen name="password_keyboard_key_height_alpha">47dip</dimen>
- <!-- Default height of a key in the password keyboard for numeric -->
- <dimen name="password_keyboard_key_height_numeric">50dip</dimen>
- <!-- Default correction for the space key in the password keyboard -->
- <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
- <dimen name="preference_widget_width">72dp</dimen>
-
- <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
- <dimen name="keyguard_lockscreen_clock_font_size">70sp</dimen>
-
<!-- Shift emergency button from the left edge by this amount. Used by landscape layout on
phones -->
<dimen name="kg_emergency_button_shift">30dp</dimen>
diff --git a/packages/Keyguard/res/values-large/dimens.xml b/packages/Keyguard/res/values-large/dimens.xml
index 8cd614d..0b5d4ad 100644
--- a/packages/Keyguard/res/values-large/dimens.xml
+++ b/packages/Keyguard/res/values-large/dimens.xml
@@ -17,13 +17,6 @@
*/
-->
<resources>
- <!-- Default height of a key in the password keyboard for alpha -->
- <dimen name="password_keyboard_key_height_alpha">75dip</dimen>
- <!-- Default height of a key in the password keyboard for numeric -->
- <dimen name="password_keyboard_key_height_numeric">75dip</dimen>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
- <dimen name="password_keyboard_height">48.0mm</dimen>
-
<!-- Minimum width of the search view text entry area. -->
<dimen name="search_view_text_min_width">192dip</dimen>
diff --git a/packages/Keyguard/res/values-sw600dp/dimens.xml b/packages/Keyguard/res/values-sw600dp/dimens.xml
index c0e3937..f8a1362 100644
--- a/packages/Keyguard/res/values-sw600dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp/dimens.xml
@@ -18,9 +18,6 @@
*/
-->
<resources>
- <!-- Size of clock font in LockScreen. -->
- <dimen name="keyguard_pattern_unlock_clock_font_size">112sp</dimen>
-
<!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
<dimen name="keyguard_lockscreen_outerring_diameter">364dp</dimen>
@@ -37,9 +34,6 @@
<!-- Size of the clock font in keyguard's status view -->
<dimen name="kg_status_clock_font_size">141dp</dimen>
- <!-- Size of the date font in keyguard's status view -->
- <dimen name="kg_status_date_font_size">25.5dp</dimen>
-
<!-- Size of the generic status lines keyguard's status view -->
<dimen name="kg_status_line_font_size">16sp</dimen>
@@ -68,4 +62,8 @@
<!-- Margin around the various security views -->
<dimen name="keyguard_muliuser_selector_margin">12dp</dimen>
+ <!-- Overload default clock widget parameters -->
+ <dimen name="widget_label_font_size">16dp</dimen>
+ <dimen name="widget_big_font_size">141dp</dimen>
+
</resources>
diff --git a/packages/Keyguard/res/values-sw720dp/dimens.xml b/packages/Keyguard/res/values-sw720dp/dimens.xml
index b29ac22..0790b79 100644
--- a/packages/Keyguard/res/values-sw720dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw720dp/dimens.xml
@@ -21,9 +21,6 @@
<!-- Size of the clock font in keyguard's status view -->
<dimen name="kg_status_clock_font_size">188dp</dimen>
- <!-- Size of the date font in keyguard's status view -->
- <dimen name="kg_status_date_font_size">34dp</dimen>
-
<!-- Size of the generic status lines keyguard's status view -->
<dimen name="kg_status_line_font_size">19sp</dimen>
diff --git a/packages/Keyguard/res/values-xlarge/dimens.xml b/packages/Keyguard/res/values-xlarge/dimens.xml
deleted file mode 100644
index b8cf287..0000000
--- a/packages/Keyguard/res/values-xlarge/dimens.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/dimens.xml
-**
-** Copyright 2006, 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.
-*/
--->
-<resources>
- <!-- Default height of a key in the password keyboard for alpha -->
- <dimen name="password_keyboard_key_height_alpha">75dip</dimen>
- <!-- Default height of a key in the password keyboard for numeric -->
- <dimen name="password_keyboard_key_height_numeric">75dip</dimen>
- <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 -->
- <dimen name="password_keyboard_height">48.0mm</dimen>
-</resources>
diff --git a/packages/Keyguard/res/values/alias.xml b/packages/Keyguard/res/values/alias.xml
index c964391..b22311e 100644
--- a/packages/Keyguard/res/values/alias.xml
+++ b/packages/Keyguard/res/values/alias.xml
@@ -34,9 +34,6 @@
<!-- Alias used to reference framework drawable in keyguard. -->
<item type="drawable" name="ic_contact_picture">@*android:drawable/ic_contact_picture</item>
- <!-- Alias used to reference framework drawable in keyguard. -->
- <item type="drawable" name="ic_lock_idle_alarm">@*android:drawable/ic_lock_idle_alarm</item>
-
<!-- Alias used to reference framework "OK" string in keyguard. -->
<item type="string" name="ok">@*android:string/ok</item>
@@ -52,4 +49,4 @@
<!-- Alias used to reference framework activity duration. -->
<item type="integer" name="config_activityDefaultDur">@*android:integer/config_activityDefaultDur</item>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/packages/Keyguard/res/values/colors.xml b/packages/Keyguard/res/values/colors.xml
index 0c56a43..a9e8061 100644
--- a/packages/Keyguard/res/values/colors.xml
+++ b/packages/Keyguard/res/values/colors.xml
@@ -23,4 +23,8 @@
<!-- FaceLock -->
<color name="facelock_spotlight_mask">#CC000000</color>
+
+ <!-- Clock -->
+ <color name="clock_white">#ffffffff</color>
+ <color name="clock_gray">#80ffffff</color>
</resources>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index ce72f43..8039b09 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -18,17 +18,6 @@
*/
-->
<resources>
- <!-- Default height of a key in the password keyboard for alpha (used by keyguard) -->
- <dimen name="password_keyboard_key_height_alpha">56dip</dimen>
- <!-- Default height of a key in the password keyboard for numeric (used by keyguard) -->
- <dimen name="password_keyboard_key_height_numeric">56dip</dimen>
- <!-- Default correction for the space key in the password keyboard (used by keyguard) -->
- <dimen name="password_keyboard_spacebar_vertical_correction">4dip</dimen>
- <!-- Default horizontal gap between keys in the password keyboard (used by keyguard) -->
- <dimen name="password_keyboard_horizontalGap">3dip</dimen>
- <!-- Default vertical gap between keys in the password keyboard (used by keyguard) -->
- <dimen name="password_keyboard_verticalGap">9dip</dimen>
-
<!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
<dimen name="keyguard_lockscreen_outerring_diameter">270dp</dimen>
@@ -47,9 +36,6 @@
<!-- Default distance from each snap target that GlowPadView considers a "hit" -->
<dimen name="glowpadview_inner_radius">15dip</dimen>
- <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
- <dimen name="keyguard_lockscreen_clock_font_size">80dip</dimen>
-
<!-- Size of status line font on Unsecure unlock LockScreen. -->
<dimen name="keyguard_lockscreen_status_line_font_size">14dip</dimen>
@@ -84,11 +70,8 @@
<!-- Size of the clock font in keyguard's status view -->
<dimen name="kg_status_clock_font_size">75dp</dimen>
- <!-- Size of the date font in keyguard's status view -->
- <dimen name="kg_status_date_font_size">15dp</dimen>
-
<!-- Size of the generic status lines keyguard's status view -->
- <dimen name="kg_status_line_font_size">13dp</dimen>
+ <dimen name="kg_status_line_font_size">12dp</dimen>
<!-- Size of margin on the right of keyguard's status view -->
<dimen name="kg_status_line_font_right_margin">16dp</dimen>
@@ -166,5 +149,12 @@
used on tablets; on phones, this size is determined by the space left by the
security mode. -->
<dimen name="kg_small_widget_height">160dp</dimen>
+
+ <!-- Default clock parameters -->
+ <dimen name="bottom_text_spacing_digital">-8dp</dimen>
+ <dimen name="label_font_size">14dp</dimen>
+ <dimen name="widget_label_font_size">12dp</dimen>
+ <dimen name="widget_big_font_size">80dp</dimen>
+ <dimen name="big_font_size">120dp</dimen>
</resources>
diff --git a/packages/Keyguard/res/values/donottranslate.xml b/packages/Keyguard/res/values/donottranslate.xml
new file mode 100644
index 0000000..71d3ed7
--- /dev/null
+++ b/packages/Keyguard/res/values/donottranslate.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- String matching the lock screen format for displaying the date. -->
+ <string name="abbrev_wday_month_day_no_year">EEE, MMMM d</string>
+ <!-- Format for describing the date, for accessibility. -->
+ <string name="full_wday_month_day_no_year">EEEE, MMMM d</string>
+</resources>
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 11f2e54..abc4483 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -94,6 +94,10 @@
progress dialog in the meantime. this is the emssage. -->
<string name="keyguard_sim_unlock_progress_dialog_message">Unlocking SIM card\u2026</string>
+ <!-- Time format strings for fall-back clock widget -->
+ <string name="keyguard_widget_12_hours_format" translatable="false">h:mm</string>
+ <!-- Time format strings for fall-back clock widget -->
+ <string name="keyguard_widget_24_hours_format" translatable="false">kk:mm</string>
<!-- Accessibility description sent when user changes the current lock screen widget. [CHAR_LIMIT=none] -->
<string name="keyguard_accessibility_widget_changed">%1$s. Widget %2$d of %3$d.</string>
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index a31f708..44f560f 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -52,5 +52,20 @@
<item name="android:windowEnterAnimation">@anim/lock_screen_enter</item>
<item name="android:windowExitAnimation">@anim/lock_screen_exit</item>
</style>
+
+ <!-- Built-in clock widget stuff -->
+ <style name="widget_label">
+ <item name="android:textStyle">bold</item>
+ <item name="android:textAllCaps">true</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ <item name="android:textSize">@dimen/kg_status_line_font_size</item>
+ </style>
+ <style name="big_thin">
+ <item name="android:textSize">@dimen/big_font_size</item>
+ <item name="android:fontFamily">sans-serif-thin</item>
+ </style>
+ <style name="widget_big_thin" parent="big_thin">
+ <item name="android:textSize">@dimen/widget_big_font_size</item>
+ </style>
</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/ClockView.java b/packages/Keyguard/src/com/android/keyguard/ClockView.java
deleted file mode 100644
index ad85e9a..0000000
--- a/packages/Keyguard/src/com/android/keyguard/ClockView.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2012 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.keyguard;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.graphics.Typeface;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.format.DateFormat;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import java.lang.ref.WeakReference;
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-
-/**
- * Displays the time
- */
-public class ClockView extends RelativeLayout {
- private static final String ANDROID_CLOCK_FONT_FILE = "/system/fonts/AndroidClock.ttf";
- private final static String M12 = "h:mm";
- private final static String M24 = "HH:mm";
-
- private Calendar mCalendar;
- private String mFormat;
- private TextView mTimeView;
- private AmPm mAmPm;
- private ContentObserver mFormatChangeObserver;
- private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced
-
- /* called by system on minute ticks */
- private final Handler mHandler = new Handler();
- private BroadcastReceiver mIntentReceiver;
-
- private static class TimeChangedReceiver extends BroadcastReceiver {
- private WeakReference<ClockView> mClock;
- private Context mContext;
-
- public TimeChangedReceiver(ClockView clock) {
- mClock = new WeakReference<ClockView>(clock);
- mContext = clock.getContext();
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- // Post a runnable to avoid blocking the broadcast.
- final boolean timezoneChanged =
- intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED);
- final ClockView clock = mClock.get();
- if (clock != null) {
- clock.mHandler.post(new Runnable() {
- public void run() {
- if (timezoneChanged) {
- clock.mCalendar = Calendar.getInstance();
- }
- clock.updateTime();
- }
- });
- } else {
- try {
- mContext.unregisterReceiver(this);
- } catch (RuntimeException e) {
- // Shouldn't happen
- }
- }
- }
- };
-
- static class AmPm {
- private TextView mAmPmTextView;
- private String mAmString, mPmString;
-
- AmPm(View parent, Typeface tf) {
- // No longer used, uncomment if we decide to use AM/PM indicator again
- // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
- if (mAmPmTextView != null && tf != null) {
- mAmPmTextView.setTypeface(tf);
- }
-
- String[] ampm = new DateFormatSymbols().getAmPmStrings();
- mAmString = ampm[0];
- mPmString = ampm[1];
- }
-
- void setShowAmPm(boolean show) {
- if (mAmPmTextView != null) {
- mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE);
- }
- }
-
- void setIsMorning(boolean isMorning) {
- if (mAmPmTextView != null) {
- mAmPmTextView.setText(isMorning ? mAmString : mPmString);
- }
- }
- }
-
- private static class FormatChangeObserver extends ContentObserver {
- private WeakReference<ClockView> mClock;
- private Context mContext;
- public FormatChangeObserver(ClockView clock) {
- super(new Handler());
- mClock = new WeakReference<ClockView>(clock);
- mContext = clock.getContext();
- }
- @Override
- public void onChange(boolean selfChange) {
- ClockView digitalClock = mClock.get();
- if (digitalClock != null) {
- digitalClock.setDateFormat();
- digitalClock.updateTime();
- } else {
- try {
- mContext.getContentResolver().unregisterContentObserver(this);
- } catch (RuntimeException e) {
- // Shouldn't happen
- }
- }
- }
- }
-
- public ClockView(Context context) {
- this(context, null);
- }
-
- public ClockView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mTimeView = (TextView) findViewById(R.id.clock_text);
- mTimeView.setTypeface(Typeface.createFromFile(ANDROID_CLOCK_FONT_FILE));
- mAmPm = new AmPm(this, null);
- mCalendar = Calendar.getInstance();
- setDateFormat();
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- mAttached++;
-
- /* monitor time ticks, time changed, timezone */
- if (mIntentReceiver == null) {
- mIntentReceiver = new TimeChangedReceiver(this);
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_TIME_TICK);
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.OWNER, filter, null, null );
- }
-
- /* monitor 12/24-hour display preference */
- if (mFormatChangeObserver == null) {
- mFormatChangeObserver = new FormatChangeObserver(this);
- mContext.getContentResolver().registerContentObserver(
- Settings.System.CONTENT_URI, true, mFormatChangeObserver);
- }
-
- updateTime();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- mAttached--;
-
- if (mIntentReceiver != null) {
- mContext.unregisterReceiver(mIntentReceiver);
- }
- if (mFormatChangeObserver != null) {
- mContext.getContentResolver().unregisterContentObserver(
- mFormatChangeObserver);
- }
-
- mFormatChangeObserver = null;
- mIntentReceiver = null;
- }
-
- void updateTime(Calendar c) {
- mCalendar = c;
- updateTime();
- }
-
- public void updateTime() {
- mCalendar.setTimeInMillis(System.currentTimeMillis());
-
- CharSequence newTime = DateFormat.format(mFormat, mCalendar);
- mTimeView.setText(newTime);
- mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
- }
-
- private void setDateFormat() {
- mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24 : M12;
- mAmPm.setShowAmPm(mFormat.equals(M12));
- }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index 0289a1f..ffb619b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -38,17 +38,9 @@
private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
private static final String TAG = "KeyguardStatusView";
- public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
- public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
- public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
- public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
-
- private SimpleDateFormat mDateFormat;
private LockPatternUtils mLockPatternUtils;
- private TextView mDateView;
private TextView mAlarmStatusView;
- private ClockView mClockView;
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@@ -81,21 +73,12 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- Resources res = getContext().getResources();
- final Locale locale = Locale.getDefault();
- final String datePattern = res.getString(R.string.system_ui_date_pattern);
- final String bestFormat = ICU.getBestDateTimePattern(datePattern, locale.toString());
- mDateFormat = new SimpleDateFormat(bestFormat, locale);
- mDateView = (TextView) findViewById(R.id.date);
+
mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
- mClockView = (ClockView) findViewById(R.id.clock_view);
mLockPatternUtils = new LockPatternUtils(getContext());
- // Use custom font in mDateView
- mDateView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
-
// Required to get Marquee to work.
- final View marqueeViews[] = { mDateView, mAlarmStatusView };
+ final View marqueeViews[] = { mAlarmStatusView };
for (int i = 0; i < marqueeViews.length; i++) {
View v = marqueeViews[i];
if (v == null) {
@@ -107,8 +90,6 @@
}
protected void refresh() {
- mClockView.updateTime();
- refreshDate();
refreshAlarmStatus(); // might as well
}
@@ -117,17 +98,12 @@
String nextAlarm = mLockPatternUtils.getNextAlarm();
if (!TextUtils.isEmpty(nextAlarm)) {
mAlarmStatusView.setText(nextAlarm);
- mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
mAlarmStatusView.setVisibility(View.VISIBLE);
} else {
mAlarmStatusView.setVisibility(View.GONE);
}
}
- void refreshDate() {
- mDateView.setText(mDateFormat.format(new Date()));
- }
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 6ab86f5..59ec777 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -2145,6 +2145,10 @@
return -1;
}
+ if (!appPath.endsWith("/")) {
+ appPath = appPath + "/";
+ }
+
// Try translating the app path into a vold path, but require that it
// belong to the calling package.
String voldPath = maybeTranslatePathForVold(appPath,
@@ -2194,9 +2198,9 @@
}
for (int i = 0; i < appPaths.length; i++) {
- final String appPath = appPaths[i].getAbsolutePath();
+ final String appPath = appPaths[i].getAbsolutePath() + "/";
if (path.startsWith(appPath)) {
- path = new File(voldPaths[i], path.substring(appPath.length() + 1))
+ path = new File(voldPaths[i], path.substring(appPath.length()))
.getAbsolutePath();
if (!path.endsWith("/")) {
path = path + "/";
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 162add4..6957bac0 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -219,6 +219,8 @@
WallpaperData mWallpaper;
IRemoteCallback mReply;
+ boolean mDimensionsChanged = false;
+
public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
mInfo = info;
mWallpaper = wallpaper;
@@ -262,6 +264,14 @@
public void attachEngine(IWallpaperEngine engine) {
synchronized (mLock) {
mEngine = engine;
+ if (mDimensionsChanged) {
+ try {
+ mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to set wallpaper dimensions", e);
+ }
+ mDimensionsChanged = false;
+ }
}
}
@@ -652,6 +662,11 @@
} catch (RemoteException e) {
}
notifyCallbacksLocked(wallpaper);
+ } else if (wallpaper.connection.mService != null) {
+ // We've attached to the service but the engine hasn't attached back to us
+ // yet. This means it will be created with the previous dimensions, so we
+ // need to update it to the new dimensions once it attaches.
+ wallpaper.connection.mDimensionsChanged = true;
}
}
}
diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/java/com/android/server/wifi/WifiController.java
index 87b4394..a3d514e 100644
--- a/services/java/com/android/server/wifi/WifiController.java
+++ b/services/java/com/android/server/wifi/WifiController.java
@@ -57,6 +57,7 @@
private int mStayAwakeConditions;
private long mIdleMillis;
private int mSleepPolicy;
+ private boolean mFirstUserSignOnSeen = false;
private AlarmManager mAlarmManager;
private PendingIntent mIdleIntent;
@@ -113,6 +114,7 @@
static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
static final int CMD_SET_AP = BASE + 10;
static final int CMD_DEFERRED_TOGGLE = BASE + 11;
+ static final int CMD_USER_PRESENT = BASE + 12;
private DefaultState mDefaultState = new DefaultState();
private StaEnabledState mStaEnabledState = new StaEnabledState();
@@ -361,6 +363,9 @@
case CMD_AIRPLANE_TOGGLED:
case CMD_EMERGENCY_MODE_CHANGED:
break;
+ case CMD_USER_PRESENT:
+ mFirstUserSignOnSeen = true;
+ break;
case CMD_DEFERRED_TOGGLE:
log("DEFERRED_TOGGLE ignored due to state change");
break;
@@ -639,6 +644,15 @@
if (msg.what == CMD_DEVICE_IDLE) {
checkLocksAndTransitionWhenDeviceIdle();
// We let default state handle the rest of work
+ } else if (msg.what == CMD_USER_PRESENT) {
+ // TLS networks can't connect until user unlocks keystore. KeyStore
+ // unlocks when the user punches PIN after the reboot. So use this
+ // trigger to get those networks connected.
+ if (mFirstUserSignOnSeen == false) {
+ mWifiStateMachine.reloadTlsNetworksAndReconnect();
+ }
+ mFirstUserSignOnSeen = true;
+ return HANDLED;
}
return NOT_HANDLED;
}
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index f93a45b..86c68f3 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -83,6 +83,7 @@
import static com.android.server.wifi.WifiController.CMD_SCREEN_OFF;
import static com.android.server.wifi.WifiController.CMD_SCREEN_ON;
import static com.android.server.wifi.WifiController.CMD_SET_AP;
+import static com.android.server.wifi.WifiController.CMD_USER_PRESENT;
import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
/**
* WifiService handles remote WiFi operation requests by implementing
@@ -1084,6 +1085,8 @@
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON)) {
mWifiController.sendMessage(CMD_SCREEN_ON);
+ } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
+ mWifiController.sendMessage(CMD_USER_PRESENT);
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
mWifiController.sendMessage(CMD_SCREEN_OFF);
} else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
@@ -1120,6 +1123,7 @@
private void registerForBroadcasts() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
+ intentFilter.addAction(Intent.ACTION_USER_PRESENT);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 2e91e03..9bbaf60 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -1232,10 +1232,10 @@
// the IME above it until it is completely gone so it doesn't drop
// behind the dialog or its full-screen scrim.
final WindowState curTarget = mInputMethodTarget;
- if (curTarget != null && w != null
+ if (curTarget != null
&& curTarget.isDisplayedLw()
&& curTarget.isClosing()
- && (curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
+ && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
return windows.indexOf(curTarget) + 1;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 6fd5acc..a8b58aa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -45,6 +45,12 @@
}
@Override
+ public void acquireWakeLockWithUid(IBinder arg0, int arg1, String arg2, String arg2_5, int arg3)
+ throws RemoteException {
+ // pass for now.
+ }
+
+ @Override
public void crash(String arg0) throws RemoteException {
// pass for now.
}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index f79a4a6..a6ae215 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -57,6 +57,7 @@
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.security.PublicKey;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
@@ -742,6 +743,26 @@
markAllNetworksDisabledExcept(INVALID_NETWORK_ID);
}
+ boolean needsUnlockedKeyStore() {
+
+ // Any network using certificates to authenticate access requires
+ // unlocked key store; unless the certificates can be stored with
+ // hardware encryption
+
+ for(WifiConfiguration config : mConfiguredNetworks.values()) {
+
+ if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP)
+ && config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
+
+ if (config.enterpriseConfig.needsSoftwareBackedKeyStore()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
private void writeIpAndProxyConfigurations() {
/* Make a copy */
@@ -1223,7 +1244,6 @@
* Keyguard settings may eventually be controlled by device policy.
* We check here if keystore is unlocked before installing
* credentials.
- * TODO: Figure a way to store these credentials for wifi alone
* TODO: Do we need a dialog here ?
*/
if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
@@ -1583,6 +1603,7 @@
}
config.enterpriseConfig.migrateCerts(mKeyStore);
+ config.enterpriseConfig.initializeSoftwareKeystoreFlag(mKeyStore);
}
private String removeDoubleQuotes(String string) {
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index e357804a..c7ebecb 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -19,8 +19,10 @@
import android.os.Parcelable;
import android.os.Process;
import android.security.Credentials;
+import android.security.KeyChain;
import android.security.KeyStore;
import android.text.TextUtils;
+import android.util.Slog;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -43,6 +45,7 @@
*/
public class WifiEnterpriseConfig implements Parcelable {
private static final String TAG = "WifiEnterpriseConfig";
+ private static final boolean DBG = false;
/**
* In old configurations, the "private_key" field was used. However, newer
* configurations use the key_id field with the engine_id set to "keystore".
@@ -91,6 +94,7 @@
private X509Certificate mCaCert;
private PrivateKey mClientPrivateKey;
private X509Certificate mClientCertificate;
+ private boolean mNeedsSoftwareKeystore = false;
/** This represents an empty value of an enterprise field.
* NULL is used at wpa_supplicant to indicate an empty value
@@ -509,6 +513,18 @@
return true;
}
+ static boolean isHardwareBackedKey(PrivateKey key) {
+ return KeyChain.isBoundKeyAlgorithm(key.getAlgorithm());
+ }
+
+ static boolean hasHardwareBackedKey(Certificate certificate) {
+ return KeyChain.isBoundKeyAlgorithm(certificate.getPublicKey().getAlgorithm());
+ }
+
+ boolean needsSoftwareBackedKeyStore() {
+ return mNeedsSoftwareKeystore;
+ }
+
boolean installKeys(android.security.KeyStore keyStore, String name) {
boolean ret = true;
String privKeyName = Credentials.USER_PRIVATE_KEY + name;
@@ -516,8 +532,23 @@
String caCertName = Credentials.CA_CERTIFICATE + name;
if (mClientCertificate != null) {
byte[] privKeyData = mClientPrivateKey.getEncoded();
- ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
- KeyStore.FLAG_ENCRYPTED);
+ if (isHardwareBackedKey(mClientPrivateKey)) {
+ // Hardware backed key store is secure enough to store keys un-encrypted, this
+ // removes the need for user to punch a PIN to get access to these keys
+ if (DBG) Slog.d(TAG, "importing keys " + name + " in hardware backed " +
+ "store");
+ ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
+ KeyStore.FLAG_NONE);
+ } else {
+ // Software backed key store is NOT secure enough to store keys un-encrypted.
+ // Save keys encrypted so they are protected with user's PIN. User will
+ // have to unlock phone before being able to use these keys and connect to
+ // networks.
+ if (DBG) Slog.d(TAG, "importing keys " + name + " in software backed store");
+ ret = keyStore.importKey(privKeyName, privKeyData, Process.WIFI_UID,
+ KeyStore.FLAG_ENCRYPTED);
+ mNeedsSoftwareKeystore = true;
+ }
if (ret == false) {
return ret;
}
@@ -561,7 +592,9 @@
Certificate cert) {
try {
byte[] certData = Credentials.convertToPem(cert);
- return keyStore.put(name, certData, Process.WIFI_UID, KeyStore.FLAG_ENCRYPTED);
+ if (DBG) Slog.d(TAG, "putting certificate " + name + " in keystore");
+ return keyStore.put(name, certData, Process.WIFI_UID, KeyStore.FLAG_NONE);
+
} catch (IOException e1) {
return false;
} catch (CertificateException e2) {
@@ -573,6 +606,7 @@
String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
// a valid client certificate is configured
if (!TextUtils.isEmpty(client)) {
+ if (DBG) Slog.d(TAG, "removing client private key and user cert");
keyStore.delKey(Credentials.USER_PRIVATE_KEY + client, Process.WIFI_UID);
keyStore.delete(Credentials.USER_CERTIFICATE + client, Process.WIFI_UID);
}
@@ -580,6 +614,7 @@
String ca = getFieldValue(CA_CERT_KEY, CA_CERT_PREFIX);
// a valid ca certificate is configured
if (!TextUtils.isEmpty(ca)) {
+ if (DBG) Slog.d(TAG, "removing CA cert");
keyStore.delete(Credentials.CA_CERTIFICATE + ca, Process.WIFI_UID);
}
}
@@ -684,6 +719,61 @@
}
}
+ void initializeSoftwareKeystoreFlag(android.security.KeyStore keyStore) {
+ String client = getFieldValue(CLIENT_CERT_KEY, CLIENT_CERT_PREFIX);
+ if (!TextUtils.isEmpty(client)) {
+ // a valid client certificate is configured
+
+ // BUGBUG: keyStore.get() never returns certBytes; because it is not
+ // taking WIFI_UID as a parameter. It always looks for certificate
+ // with SYSTEM_UID, and never finds any Wifi certificates. Assuming that
+ // all certificates need software keystore until we get the get() API
+ // fixed.
+
+ mNeedsSoftwareKeystore = true;
+
+ /*
+ try {
+
+ if (DBG) Slog.d(TAG, "Loading client certificate " + Credentials
+ .USER_CERTIFICATE + client);
+
+ CertificateFactory factory = CertificateFactory.getInstance("X.509");
+ if (factory == null) {
+ Slog.e(TAG, "Error getting certificate factory");
+ return;
+ }
+
+ byte[] certBytes = keyStore.get(Credentials.USER_CERTIFICATE + client);
+ if (certBytes != null) {
+ Certificate cert = (X509Certificate) factory.generateCertificate(
+ new ByteArrayInputStream(certBytes));
+
+ if (cert != null) {
+ mNeedsSoftwareKeystore = hasHardwareBackedKey(cert);
+
+ if (DBG) Slog.d(TAG, "Loaded client certificate " + Credentials
+ .USER_CERTIFICATE + client);
+ if (DBG) Slog.d(TAG, "It " + (mNeedsSoftwareKeystore ? "needs" :
+ "does not need" ) + " software key store");
+ } else {
+ Slog.d(TAG, "could not generate certificate");
+ }
+ } else {
+ Slog.e(TAG, "Could not load client certificate " + Credentials
+ .USER_CERTIFICATE + client);
+ mNeedsSoftwareKeystore = true;
+ }
+
+ } catch(CertificateException e) {
+ Slog.e(TAG, "Could not read certificates");
+ mCaCert = null;
+ mClientCertificate = null;
+ }
+ */
+ }
+ }
+
private String removeDoubleQuotes(String string) {
if (TextUtils.isEmpty(string)) return "";
int length = string.length();
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 798bc2e..cf09836 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -426,6 +426,8 @@
static final int CMD_IP_ADDRESS_UPDATED = BASE + 140;
/* An IP address was removed from our interface */
static final int CMD_IP_ADDRESS_REMOVED = BASE + 141;
+ /* Reload all networks and reconnect */
+ static final int CMD_RELOAD_TLS_AND_RECONNECT = BASE + 142;
/* Wifi state machine modes of operation */
/* CONNECT_MODE - connect to any 'known' AP when it becomes available */
@@ -1320,6 +1322,14 @@
}
/**
+ * Reload networks and then reconnect; helps load correct data for TLS networks
+ */
+
+ public void reloadTlsNetworksAndReconnect() {
+ sendMessage(CMD_RELOAD_TLS_AND_RECONNECT);
+ }
+
+ /**
* Add a network synchronously
*
* @return network id of the new network
@@ -2445,6 +2455,7 @@
case CMD_DISCONNECT:
case CMD_RECONNECT:
case CMD_REASSOCIATE:
+ case CMD_RELOAD_TLS_AND_RECONNECT:
case WifiMonitor.SUP_CONNECTION_EVENT:
case WifiMonitor.SUP_DISCONNECTION_EVENT:
case WifiMonitor.NETWORK_CONNECTION_EVENT:
@@ -3395,6 +3406,13 @@
case CMD_REASSOCIATE:
mWifiNative.reassociate();
break;
+ case CMD_RELOAD_TLS_AND_RECONNECT:
+ if (mWifiConfigStore.needsUnlockedKeyStore()) {
+ logd("Reconnecting to give a chance to un-connected TLS networks");
+ mWifiNative.disconnect();
+ mWifiNative.reconnect();
+ }
+ break;
case WifiManager.CONNECT_NETWORK:
/* The connect message can contain a network id passed as arg1 on message or
* or a config passed as obj on message.