Merge "Sometimes printer selection from all printers activity does not work." into klp-dev
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 800ead9..b741cc5 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -16,6 +16,8 @@
package android.app;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -267,18 +269,21 @@
/**
* Broadcast intent action sent by the download manager when a download completes.
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
/**
* Broadcast intent action sent by the download manager when the user clicks on a running
* download, either from a system notification or from the downloads UI.
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public final static String ACTION_NOTIFICATION_CLICKED =
"android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
/**
* Intent action to launch an activity to display all downloads.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public final static String ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS";
/**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 2172a7b..e2bc80a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -923,42 +923,6 @@
}
/**
- * Create a listening, L2CAP Bluetooth socket.
- * <p>A remote device connecting to this socket will optionally be
- * authenticated and communication on this socket will optionally be
- * encrypted.
- * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
- * connections from a listening {@link BluetoothServerSocket}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * @param secure whether security and authentication are required
- * @param fixedChannel whether we're looking for a PSM-based connection or a fixed channel
- * @param channel L2CAP PSM or channel to use
- * @return a listening L2CAP BluetoothServerSocket
- * @throws IOException on error, for example Bluetooth not available, or
- * insufficient permissions, or channel in use.
- * @hide
- */
- public BluetoothServerSocket listenUsingL2CapOn(boolean secure, boolean fixedChannel,
- int channel) throws IOException {
- BluetoothServerSocket socket;
-
- if (fixedChannel) {
- channel |= BluetoothSocket.PORT_MASK_FIXED_CHAN;
- }
-
- socket = new BluetoothServerSocket(
- BluetoothSocket.TYPE_L2CAP, secure, secure, channel);
- int errno = socket.mSocket.bindListen();
- if (errno != 0) {
- //TODO(BT): Throw the same exception error code
- // that the previous code was using.
- //socket.mSocket.throwErrnoNative(errno);
- throw new IOException("Error: " + errno);
- }
- return socket;
- }
-
- /**
* Create a listening, secure RFCOMM Bluetooth socket.
* <p>A remote device connecting to this socket will be authenticated and
* communication on this socket will be encrypted.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 1efdc81..5eb642c 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1172,33 +1172,6 @@
return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null);
}
-
- /**
- * Construct a L2CAP socket ready to start an outgoing connection.
- * Call #connect on the returned #BluetoothSocket to begin the connection.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- *
- * @param secure select whether security will be required
- * @param fixedChannel select if this will be a "fixed channel" L2CAP connection
- * or a PSM-based connection
- * @param channel fixed channel or PSM to connect to
- * @return a L2CAP BluetoothSocket
- * @throws IOException on error, for example Bluetooth not available, or
- * insufficient permissions.
- * @hide
- */
- public BluetoothSocket createL2CapSocket(boolean secure, boolean fixedChannel, int channel)
- throws IOException {
-
- if (fixedChannel) {
- channel |= BluetoothSocket.PORT_MASK_FIXED_CHAN;
- }
-
- return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, secure, secure, this,
- channel, null);
- }
-
-
/**
* Check that a pin is valid and convert to byte array.
*
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 191bf67..d10eaea 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -103,8 +103,6 @@
/*package*/ static final int SEC_FLAG_ENCRYPT = 1;
/*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
- /*package*/ static final int PORT_MASK_FIXED_CHAN = 1 << 16;
-
private final int mType; /* one of TYPE_RFCOMM etc */
private BluetoothDevice mDevice; /* remote device */
private String mAddress; /* remote address */
@@ -117,7 +115,7 @@
private LocalSocket mSocket;
private InputStream mSocketIS;
private OutputStream mSocketOS;
- private int mPort; /* RFCOMM channel or L2CAP psm/channel */
+ private int mPort; /* RFCOMM channel or L2CAP psm */
private int mFd;
private String mServiceName;
private static int PROXY_CONNECTION_TIMEOUT = 5000;
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index 612c67f..eb7426e 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -26,6 +26,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
/**
* Abstract Loader that provides an {@link AsyncTask} to do the work. See
@@ -123,6 +124,8 @@
}
}
+ private final Executor mExecutor;
+
volatile LoadTask mTask;
volatile LoadTask mCancellingTask;
@@ -131,7 +134,13 @@
Handler mHandler;
public AsyncTaskLoader(Context context) {
+ this(context, AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+
+ /** {@hide} */
+ public AsyncTaskLoader(Context context, Executor executor) {
super(context);
+ mExecutor = executor;
}
/**
@@ -223,7 +232,7 @@
}
}
if (DEBUG) Slog.v(TAG, "Executing: " + mTask);
- mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+ mTask.executeOnExecutor(mExecutor, (Void[]) null);
}
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 798ad7b..f5ee367 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -369,10 +369,30 @@
}
mDeviceIdList = new ArrayList<String>();
+ CameraMetadataNative info = new CameraMetadataNative();
for (int i = 0; i < numCameras; ++i) {
// Non-removable cameras use integers starting at 0 for their
// identifiers
- mDeviceIdList.add(String.valueOf(i));
+ boolean isDeviceSupported = false;
+ try {
+ mCameraService.getCameraCharacteristics(i, info);
+ if (!info.isEmpty()) {
+ isDeviceSupported = true;
+ } else {
+ throw new AssertionError("Expected to get non-empty characteristics");
+ }
+ } catch(IllegalArgumentException e) {
+ // Got a BAD_VALUE from service, meaning that this
+ // device is not supported.
+ } catch(CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch(RemoteException e) {
+ // impossible
+ }
+
+ if (isDeviceSupported) {
+ mDeviceIdList.add(String.valueOf(i));
+ }
}
}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index ad6839b..f69cad0 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -118,6 +118,7 @@
* sense for apps that can support large-scale search of music, such as services connected
* to an online database of music which can be streamed and played on the device.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
"android.media.action.MEDIA_PLAY_FROM_SEARCH";
@@ -134,6 +135,7 @@
* sense for apps that can support large-scale search of text media, such as services connected
* to an online database of books and/or magazines which can be read on the device.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH =
"android.media.action.TEXT_OPEN_FROM_SEARCH";
@@ -150,6 +152,7 @@
* sense for apps that can support large-scale search of video, such as services connected to an
* online database of videos which can be streamed and played on the device.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH =
"android.media.action.VIDEO_PLAY_FROM_SEARCH";
@@ -202,6 +205,7 @@
/**
* The name of the Intent action used to launch a camera in still image mode.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
/**
@@ -216,12 +220,14 @@
* this flag is used, so launching more than one activity is strongly
* discouraged.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
"android.media.action.STILL_IMAGE_CAMERA_SECURE";
/**
* The name of the Intent action used to launch a camera in video mode.
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
/**
@@ -235,6 +241,7 @@
* value of EXTRA_OUTPUT.
* @see #EXTRA_OUTPUT
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
/**
@@ -256,6 +263,7 @@
* @see #ACTION_IMAGE_CAPTURE
* @see #EXTRA_OUTPUT
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_IMAGE_CAPTURE_SECURE =
"android.media.action.IMAGE_CAPTURE_SECURE";
@@ -274,6 +282,7 @@
* @see #EXTRA_SIZE_LIMIT
* @see #EXTRA_DURATION_LIMIT
*/
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public final static String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
/**
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 6a6f027..8c1cf5f 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -84,14 +84,14 @@
public static final int ASSERT = 7;
/**
- * Exception class used to capture a stack trace in {@link #wtf()}.
+ * Exception class used to capture a stack trace in {@link #wtf}.
*/
private static class TerribleFailure extends Exception {
TerribleFailure(String msg, Throwable cause) { super(msg, cause); }
}
/**
- * Interface to handle terrible failures from {@link #wtf()}.
+ * Interface to handle terrible failures from {@link #wtf}.
*
* @hide
*/
@@ -257,6 +257,15 @@
}
/**
+ * Like {@link #wtf(String, String)}, but also writes to the log the full
+ * call stack.
+ * @hide
+ */
+ public static int wtfStack(String tag, String msg) {
+ return wtfStack(LOG_ID_MAIN, tag, msg);
+ }
+
+ /**
* What a Terrible Failure: Report an exception that should never happen.
* Similar to {@link #wtf(String, String)}, with an exception to log.
* @param tag Used to identify the source of a log message.
@@ -274,8 +283,18 @@
* @param tr An exception to log. May be null.
*/
public static int wtf(String tag, String msg, Throwable tr) {
+ return wtf(LOG_ID_MAIN, tag, msg, tr);
+ }
+
+ static int wtfStack(int logId, String tag, String msg) {
+ TerribleFailure here = new TerribleFailure("here", null);
+ here.fillInStackTrace();
+ return wtf(logId, tag, msg, here);
+ }
+
+ static int wtf(int logId, String tag, String msg, Throwable tr) {
TerribleFailure what = new TerribleFailure(msg, tr);
- int bytes = println_native(LOG_ID_MAIN, ASSERT, tag, msg + '\n' + getStackTraceString(tr));
+ int bytes = println_native(logId, ASSERT, tag, msg + '\n' + getStackTraceString(tr));
sWtfHandler.onTerribleFailure(tag, what);
return bytes;
}
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index ecf5ea1..a5c22ff 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -78,6 +78,22 @@
msg + '\n' + Log.getStackTraceString(tr));
}
+ public static int wtf(String tag, String msg) {
+ return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null);
+ }
+
+ public static int wtfStack(String tag, String msg) {
+ return Log.wtfStack(Log.LOG_ID_SYSTEM, tag, msg);
+ }
+
+ public static int wtf(String tag, Throwable tr) {
+ return Log.wtf(Log.LOG_ID_SYSTEM, tag, tr.getMessage(), tr);
+ }
+
+ public static int wtf(String tag, String msg, Throwable tr) {
+ return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, tr);
+ }
+
public static int println(int priority, String tag, String msg) {
return Log.println_native(Log.LOG_ID_SYSTEM, priority, tag, msg);
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1e4b29f..4366fb7 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -478,7 +478,7 @@
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
;
if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
- mLayout.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+ mLayout.flags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
}
mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 76ebb6f..89c74f1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -82,7 +82,6 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Locale;
/**
* The top of a view hierarchy, implementing the needed protocol between View
@@ -468,7 +467,7 @@
if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
if (!compatibilityInfo.supportsScreen()) {
- attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+ attrs.flags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
mLastInCompatMode = true;
}
@@ -750,7 +749,7 @@
mClientWindowLayoutFlags = attrs.flags;
// preserve compatible window flag if exists.
int compatibleWindowFlag =
- mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+ mWindowAttributes.flags & WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
// transfer over system UI visibility values as they carry current state.
attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility;
attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
@@ -1147,10 +1146,10 @@
mFullRedrawNeeded = true;
mLayoutRequested = true;
if (mLastInCompatMode) {
- params.flags &= ~WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+ params.flags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
mLastInCompatMode = false;
} else {
- params.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+ params.flags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
mLastInCompatMode = true;
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c9c74e7..53f4d77 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -841,6 +841,15 @@
// ----- HIDDEN FLAGS.
// These start at the high bit and go down.
+ /**
+ * Flag for a window in local focus mode.
+ * Window in local focus mode can control focus independent of window manager using
+ * {@link Window#setLocalFocus(boolean, boolean)}.
+ * Usually window in this mode will not get touch/key events from window manager, but will
+ * get events only via local injection using {@link Window#injectInputEvent(InputEvent)}.
+ */
+ public static final int FLAG_LOCAL_FOCUS_MODE = 0x10000000;
+
/** Window flag: Enable touches to slide out of a window into neighboring
* windows in mid-gesture instead of being captured for the duration of
* the gesture.
@@ -851,7 +860,7 @@
*
* {@hide}
*/
- public static final int FLAG_SLIPPERY = 0x04000000;
+ public static final int FLAG_SLIPPERY = 0x20000000;
/**
* Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU}
@@ -864,29 +873,8 @@
*
* {@hide}
*/
- public static final int FLAG_NEEDS_MENU_KEY = 0x08000000;
+ public static final int FLAG_NEEDS_MENU_KEY = 0x40000000;
- /**
- * Flag for a window in local focus mode.
- * Window in local focus mode can control focus independent of window manager using
- * {@link Window#setLocalFocus(boolean, boolean)}.
- * Usually window in this mode will not get touch/key events from window manager, but will
- * get events only via local injection using {@link Window#injectInputEvent(InputEvent)}.
- */
- public static final int FLAG_LOCAL_FOCUS_MODE = 0x10000000;
-
- /** Window flag: special flag to limit the size of the window to be
- * original size ([320x480] x density). Used to create window for applications
- * running under compatibility mode.
- *
- * {@hide} */
- public static final int FLAG_COMPATIBLE_WINDOW = 0x20000000;
-
- /** Window flag: a special option intended for system dialogs. When
- * this flag is set, the window will demand focus unconditionally when
- * it is created.
- * {@hide} */
- public static final int FLAG_SYSTEM_ERROR = 0x40000000;
/**
* Various behavioral options/flags. Default is none.
@@ -1045,6 +1033,19 @@
* {@hide} */
public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 0x00000040;
+ /** Window flag: special flag to limit the size of the window to be
+ * original size ([320x480] x density). Used to create window for applications
+ * running under compatibility mode.
+ *
+ * {@hide} */
+ public static final int PRIVATE_FLAG_COMPATIBLE_WINDOW = 0x00000080;
+
+ /** Window flag: a special option intended for system dialogs. When
+ * this flag is set, the window will demand focus unconditionally when
+ * it is created.
+ * {@hide} */
+ public static final int PRIVATE_FLAG_SYSTEM_ERROR = 0x00000100;
+
/**
* Control flags that are private to the platform.
* @hide
@@ -1783,7 +1784,7 @@
sb.append(" rotAnim=");
sb.append(rotationAnimation);
}
- if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+ if ((flags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0) {
sb.append(" compatible=true");
}
if (systemUiVisibility != 0) {
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index bb4a4cf..30752e0 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -68,6 +68,8 @@
// Minimum velocity that will be absorbed
private static final int MIN_VELOCITY = 100;
+ // Maximum velocity, clamps at this value
+ private static final int MAX_VELOCITY = 10000;
private static final float EPSILON = 0.001f;
@@ -115,7 +117,7 @@
private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f;
private static final int VELOCITY_EDGE_FACTOR = 8;
- private static final int VELOCITY_GLOW_FACTOR = 16;
+ private static final int VELOCITY_GLOW_FACTOR = 12;
private int mState = STATE_IDLE;
@@ -283,10 +285,10 @@
*/
public void onAbsorb(int velocity) {
mState = STATE_ABSORB;
- velocity = Math.max(MIN_VELOCITY, Math.abs(velocity));
+ velocity = Math.min(Math.max(MIN_VELOCITY, Math.abs(velocity)), MAX_VELOCITY);
mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mDuration = 0.1f + (velocity * 0.03f);
+ mDuration = 0.15f + (velocity * 0.02f);
// The edge should always be at least partially visible, regardless
// of velocity.
@@ -294,7 +296,7 @@
mEdgeScaleY = mEdgeScaleYStart = 0.f;
// The glow depends more on the velocity, and therefore starts out
// nearly invisible.
- mGlowAlphaStart = 0.5f;
+ mGlowAlphaStart = 0.3f;
mGlowScaleYStart = 0.f;
// Factor the velocity by 8. Testing on device shows this works best to
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index a95bac8..430e43a 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -44,6 +44,7 @@
public final class ProcessStats implements Parcelable {
static final String TAG = "ProcessStats";
static final boolean DEBUG = false;
+ static final boolean DEBUG_PARCEL = false;
public static final String SERVICE_NAME = "procstats";
@@ -1076,7 +1077,7 @@
final int[] table = new int[size];
for (int i=0; i<size; i++) {
table[i] = in.readInt();
- if (DEBUG) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
+ if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
+ ProcessStats.printLongOffset(table[i]));
if (!validateLongOffset(table[i])) {
Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: "
@@ -1294,10 +1295,10 @@
byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
while (true) {
int amt = stream.read(data, pos, data.length-pos);
- if (DEBUG) Slog.i("foo", "Read " + amt + " bytes at " + pos
+ if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
+ " of avail " + data.length);
if (amt < 0) {
- if (DEBUG) Slog.i("foo", "**** FINISHED READING: pos=" + pos
+ if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
+ " len=" + data.length);
outLen[0] = pos;
return data;
@@ -1305,7 +1306,7 @@
pos += amt;
if (pos >= data.length) {
byte[] newData = new byte[pos+16384];
- if (DEBUG) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
+ if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
+ newData.length);
System.arraycopy(data, 0, newData, 0, pos);
data = newData;
@@ -1422,12 +1423,13 @@
return;
}
}
- if (DEBUG) Slog.d(TAG, "Adding process: " + procName + " " + uid + " " + proc);
+ if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
+ + " " + proc);
mProcesses.put(procName, uid, proc);
}
}
- if (DEBUG) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
+ if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
int NPKG = in.readInt();
if (NPKG < 0) {
@@ -1468,10 +1470,10 @@
return;
}
int hasProc = in.readInt();
- if (DEBUG) Slog.d(TAG, "Reading package " + pkgName + " " + uid
+ if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
+ " process " + procName + " hasProc=" + hasProc);
ProcessState commonProc = mProcesses.get(procName, uid);
- if (DEBUG) Slog.d(TAG, "Got common proc " + procName + " " + uid
+ if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
+ ": " + commonProc);
if (commonProc == null) {
mReadError = "no common proc: " + procName;
@@ -1493,11 +1495,11 @@
return;
}
}
- if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " process: "
+ if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
+ procName + " " + uid + " " + proc);
pkgState.mProcesses.put(procName, proc);
} else {
- if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " process: "
+ if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
+ procName + " " + uid + " " + commonProc);
pkgState.mProcesses.put(procName, commonProc);
}
@@ -1522,7 +1524,7 @@
if (!serv.readFromParcel(in)) {
return;
}
- if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " service: "
+ if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
+ serviceName + " " + uid + " " + serv);
pkgState.mServices.put(serviceName, serv);
}
@@ -1531,7 +1533,7 @@
mIndexToCommonString = null;
- if (DEBUG) Slog.d(TAG, "Successfully read procstats!");
+ if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
}
int addLongData(int index, int type, int num) {
@@ -1577,7 +1579,7 @@
if (idx >= LONGS_SIZE) {
return false;
}
- if (DEBUG) Slog.d(TAG, "Validated long " + printLongOffset(off)
+ if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off)
+ ": " + getLong(off, 0));
return true;
}
@@ -1639,13 +1641,16 @@
if (commonProc == null) {
commonProc = new ProcessState(this, packageName, uid, processName);
mProcesses.put(processName, uid, commonProc);
+ if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
}
if (!commonProc.mMultiPackage) {
if (packageName.equals(commonProc.mPackage)) {
// This common process is not in use by multiple packages, and
// is for the calling package, so we can just use it directly.
ps = commonProc;
+ if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
} else {
+ if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
// This common process has not been in use by multiple packages,
// but it was created for a different package than the caller.
// We need to convert it to a multi-package process.
@@ -1659,22 +1664,39 @@
// that under the now unique state for its original package name.
final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage, uid);
if (commonPkgState != null) {
- commonPkgState.mProcesses.put(commonProc.mName, commonProc.clone(
- commonProc.mPackage, now));
+ ProcessState cloned = commonProc.clone(commonProc.mPackage, now);
+ if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage
+ + ": " + cloned);
+ commonPkgState.mProcesses.put(commonProc.mName, cloned);
+ // If this has active services, we need to update their process pointer
+ // to point to the new package-specific process state.
+ for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
+ ServiceState ss = commonPkgState.mServices.valueAt(i);
+ if (ss.mProc == commonProc) {
+ if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: "
+ + ss);
+ ss.mProc = cloned;
+ } else if (DEBUG) {
+ Slog.d(TAG, "GETPROC leaving proc of " + ss);
+ }
+ }
} else {
Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage
+ "/" + uid + " for proc " + commonProc.mName);
}
// And now make a fresh new process state for the new package name.
ps = new ProcessState(commonProc, packageName, uid, processName, now);
+ if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
}
} else {
// The common process is for multiple packages, we need to create a
// separate object for the per-package data.
ps = new ProcessState(commonProc, packageName, uid, processName,
SystemClock.uptimeMillis());
+ if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
}
pkgState.mProcesses.put(processName, ps);
+ if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
return ps;
}
@@ -1683,12 +1705,14 @@
final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid);
ProcessStats.ServiceState ss = as.mServices.get(className);
if (ss != null) {
+ if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
return ss;
}
final ProcessStats.ProcessState ps = processName != null
? getProcessStateLocked(packageName, uid, processName) : null;
ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps);
as.mServices.put(className, ss);
+ if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
return ss;
}
@@ -1719,7 +1743,7 @@
}
public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
- boolean dumpAll) {
+ boolean dumpAll, boolean activeOnly) {
long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
mStartTime, now);
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
@@ -1746,6 +1770,11 @@
if (!dumpSummary || dumpAll) {
for (int iproc=0; iproc<NPROCS; iproc++) {
ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+ if (activeOnly && !proc.isInUse()) {
+ pw.print(" (Not active: ");
+ pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
+ continue;
+ }
pw.print(" Process ");
pw.print(pkgState.mProcesses.keyAt(iproc));
pw.print(" (");
@@ -1761,12 +1790,22 @@
} else {
ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
for (int iproc=0; iproc<NPROCS; iproc++) {
- procs.add(pkgState.mProcesses.valueAt(iproc));
+ ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+ if (activeOnly && !proc.isInUse()) {
+ continue;
+ }
+ procs.add(proc);
}
dumpProcessSummaryLocked(pw, " ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
NON_CACHED_PROC_STATES, now, totalTime);
}
for (int isvc=0; isvc<NSRVS; isvc++) {
+ ServiceState svc = pkgState.mServices.valueAt(isvc);
+ if (activeOnly && !svc.isInUse()) {
+ pw.print(" (Not active: ");
+ pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
+ continue;
+ }
if (dumpAll) {
pw.print(" Service ");
} else {
@@ -1774,7 +1813,6 @@
}
pw.print(pkgState.mServices.keyAt(isvc));
pw.println(":");
- ServiceState svc = pkgState.mServices.valueAt(isvc);
pw.print(" Process: "); pw.println(svc.mProcessName);
dumpServiceStats(pw, " ", " ", " ", "Running", svc,
svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
@@ -1789,7 +1827,9 @@
svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll);
if (dumpAll) {
- pw.print(" mActive="); pw.println(svc.mActive);
+ if (svc.mOwner != null) {
+ pw.print(" mOwner="); pw.println(svc.mOwner);
+ }
}
}
}
@@ -1816,6 +1856,10 @@
pw.println("Per-Process Stats:");
printedHeader = true;
}
+ if (activeOnly && !proc.isInUse()) {
+ pw.print(" (Not active: "); pw.print(procName); pw.println(")");
+ continue;
+ }
pw.print(" * "); pw.print(procName); pw.print(" / ");
UserHandle.formatUid(pw, uid);
pw.print(" ("); pw.print(proc.mDurationsTableSize);
@@ -1838,7 +1882,7 @@
pw.println();
if (dumpSummary) {
pw.println("Summary:");
- dumpSummaryLocked(pw, reqPackage, now);
+ dumpSummaryLocked(pw, reqPackage, now, activeOnly);
} else {
dumpTotalsLocked(pw, now);
}
@@ -1916,11 +1960,11 @@
}
}
- public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now) {
+ public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
mStartTime, now);
dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
- ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage);
+ ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
pw.println();
dumpTotalsLocked(pw, now);
}
@@ -1961,9 +2005,9 @@
void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
int[] screenStates, int[] memStates, int[] procStates,
- int[] sortProcStates, long now, long totalTime, String reqPackage) {
+ int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
- procStates, sortProcStates, now, reqPackage);
+ procStates, sortProcStates, now, reqPackage, activeOnly);
if (procs.size() > 0) {
if (header != null) {
pw.println();
@@ -1975,7 +2019,8 @@
}
public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
- int[] procStates, int sortProcStates[], long now, String reqPackage) {
+ int[] procStates, int sortProcStates[], long now, String reqPackage,
+ boolean activeOnly) {
ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
for (int ip=0; ip<pkgMap.size(); ip++) {
@@ -1987,6 +2032,9 @@
PackageState state = procs.valueAt(iu);
for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
ProcessState proc = state.mProcesses.valueAt(iproc);
+ if (activeOnly && !proc.isInUse()) {
+ continue;
+ }
foundProcs.add(proc.mCommonProcess);
}
}
@@ -1994,8 +2042,7 @@
ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
for (int i=0; i<foundProcs.size(); i++) {
ProcessState proc = foundProcs.valueAt(i);
- if (computeProcessTimeLocked(proc, screenStates, memStates,
- procStates, now) > 0) {
+ if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) {
outProcs.add(proc);
if (procStates != sortProcStates) {
computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now);
@@ -2229,7 +2276,7 @@
void writeDurationsToParcel(Parcel out) {
out.writeInt(mDurationsTableSize);
for (int i=0; i<mDurationsTableSize; i++) {
- if (DEBUG) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
+ if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
+ printLongOffset(mDurationsTable[i]));
out.writeInt(mDurationsTable[i]);
}
@@ -2350,6 +2397,7 @@
pnew.mAvgCachedKillPss = mAvgCachedKillPss;
pnew.mMaxCachedKillPss = mMaxCachedKillPss;
pnew.mActive = mActive;
+ pnew.mNumActiveServices = mNumActiveServices;
pnew.mNumStartedServices = mNumStartedServices;
return pnew;
}
@@ -2396,7 +2444,7 @@
if (!mDead) {
return;
}
- throw new IllegalStateException("ProcessState dead: name=" + mName
+ Slog.wtfStack(TAG, "ProcessState dead: name=" + mName
+ " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
}
@@ -2405,7 +2453,7 @@
writeDurationsToParcel(out);
out.writeInt(mPssTableSize);
for (int i=0; i<mPssTableSize; i++) {
- if (DEBUG) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
+ if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
+ printLongOffset(mPssTable[i]));
out.writeInt(mPssTable[i]);
}
@@ -2424,11 +2472,11 @@
if (fully) {
mMultiPackage = multiPackage;
}
- if (DEBUG) Slog.d(TAG, "Reading durations table...");
+ if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
if (!readDurationsFromParcel(in)) {
return false;
}
- if (DEBUG) Slog.d(TAG, "Reading pss table...");
+ if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
mPssTable = mStats.readTableFromParcel(in, mName, "pss");
if (mPssTable == BAD_TABLE) {
return false;
@@ -2512,21 +2560,34 @@
mStartTime = now;
}
- void incActiveServices() {
+ void incActiveServices(String serviceName) {
+ if (DEBUG && "".equals(mName)) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
+ + " to " + (mNumActiveServices+1), here);
+ }
if (mCommonProcess != this) {
- mCommonProcess.incActiveServices();
+ mCommonProcess.incActiveServices(serviceName);
}
mNumActiveServices++;
}
- void decActiveServices() {
+ void decActiveServices(String serviceName) {
+ if (DEBUG && "".equals(mName)) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
+ + " to " + (mNumActiveServices-1), here);
+ }
if (mCommonProcess != this) {
- mCommonProcess.decActiveServices();
+ mCommonProcess.decActiveServices(serviceName);
}
mNumActiveServices--;
if (mNumActiveServices < 0) {
- throw new IllegalStateException("Proc active services underrun: pkg="
- + mPackage + " uid=" + mUid + " name=" + mName);
+ Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
+ + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
+ mNumActiveServices = 0;
}
}
@@ -2548,8 +2609,9 @@
if (mNumStartedServices == 0 && mCurState == STATE_SERVICE_RESTARTING) {
setState(STATE_NOTHING, memFactor, now, null);
} else if (mNumStartedServices < 0) {
- throw new IllegalStateException("Proc started services underrun: pkg="
+ Slog.wtfStack(TAG, "Proc started services underrun: pkg="
+ mPackage + " uid=" + mUid + " name=" + mName);
+ mNumStartedServices = 0;
}
}
@@ -2689,8 +2751,7 @@
// The array map is still pointing to a common process state
// that is now shared across packages. Update it to point to
// the new per-package state.
- ProcessState proc = mStats.mPackages.get(pkgName,
- mUid).mProcesses.get(mName);
+ ProcessState proc = mStats.mPackages.get(pkgName, mUid).mProcesses.get(mName);
if (proc == null) {
throw new IllegalStateException("Didn't create per-package process");
}
@@ -2717,11 +2778,13 @@
PackageState pkg = mStats.mPackages.get(pkgList.keyAt(index), proc.mUid);
if (pkg == null) {
throw new IllegalStateException("No existing package "
- + pkgList.keyAt(index) + " for multi-proc " + proc.mName);
+ + pkgList.keyAt(index) + "/" + proc.mUid
+ + " for multi-proc " + proc.mName);
}
proc = pkg.mProcesses.get(proc.mName);
if (proc == null) {
- throw new IllegalStateException("Didn't create per-package process");
+ throw new IllegalStateException("Didn't create per-package process "
+ + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
}
pkgList.setValueAt(index, proc);
}
@@ -2770,6 +2833,17 @@
int idx = binarySearch(mPssTable, mPssTableSize, state);
return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
}
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
+ .append(" ").append(mName).append("/").append(mUid)
+ .append(" pkg=").append(mPackage);
+ if (mMultiPackage) sb.append(" (multi)");
+ if (mCommonProcess != this) sb.append(" (sub)");
+ sb.append("}");
+ return sb.toString();
+ }
}
public static final class ServiceState extends DurationsTable {
@@ -2777,7 +2851,7 @@
public final String mProcessName;
ProcessState mProc;
- int mActive = 0;
+ Object mOwner;
public static final int SERVICE_RUN = 0;
public static final int SERVICE_STARTED = 1;
@@ -2809,27 +2883,69 @@
mProc = proc;
}
- public void makeActive() {
- if (mActive == 0) {
- mProc.incActiveServices();
+ public void applyNewOwner(Object newOwner) {
+ if (mOwner != newOwner) {
+ if (mOwner == null) {
+ mOwner = newOwner;
+ mProc.incActiveServices(mName);
+ } else {
+ // There was already an old owner, reset this object for its
+ // new owner.
+ mOwner = newOwner;
+ if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
+ || mExecState != STATE_NOTHING) {
+ long now = SystemClock.uptimeMillis();
+ if (mStartedState != STATE_NOTHING) {
+ if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+ + " from " + mOwner + " while started: pkg="
+ + mPackage + " service=" + mName + " proc=" + mProc);
+ setStarted(false, 0, now);
+ }
+ if (mBoundState != STATE_NOTHING) {
+ if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+ + " from " + mOwner + " while bound: pkg="
+ + mPackage + " service=" + mName + " proc=" + mProc);
+ setBound(false, 0, now);
+ }
+ if (mExecState != STATE_NOTHING) {
+ if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+ + " from " + mOwner + " while executing: pkg="
+ + mPackage + " service=" + mName + " proc=" + mProc);
+ setExecuting(false, 0, now);
+ }
+ }
+ }
}
- mActive++;
}
- public void makeInactive() {
- /*
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.i(TAG, "Making " + this + " inactive", here);
- */
- mActive--;
- if (mActive == 0) {
- mProc.decActiveServices();
+ public void clearCurrentOwner(Object owner) {
+ if (mOwner == owner) {
+ mOwner = null;
+ mProc.decActiveServices(mName);
+ if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
+ || mExecState != STATE_NOTHING) {
+ long now = SystemClock.uptimeMillis();
+ if (mStartedState != STATE_NOTHING) {
+ Slog.wtfStack(TAG, "Service owner " + owner + " cleared while started: pkg="
+ + mPackage + " service=" + mName + " proc=" + mProc);
+ setStarted(false, 0, now);
+ }
+ if (mBoundState != STATE_NOTHING) {
+ Slog.wtfStack(TAG, "Service owner " + owner + " cleared while bound: pkg="
+ + mPackage + " service=" + mName + " proc=" + mProc);
+ setBound(false, 0, now);
+ }
+ if (mExecState != STATE_NOTHING) {
+ Slog.wtfStack(TAG, "Service owner " + owner + " cleared while exec: pkg="
+ + mPackage + " service=" + mName + " proc=" + mProc);
+ setExecuting(false, 0, now);
+ }
+ }
}
}
public boolean isInUse() {
- return mActive > 0;
+ return mOwner != null;
}
void add(ServiceState other) {
@@ -2904,8 +3020,8 @@
}
public void setStarted(boolean started, int memFactor, long now) {
- if (mActive <= 0) {
- throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
+ if (mOwner == null) {
+ Slog.wtf(TAG, "Starting service " + this + " without owner");
}
final boolean wasStarted = mStartedState != STATE_NOTHING;
final int state = started ? memFactor : STATE_NOTHING;
@@ -2931,8 +3047,8 @@
}
public void setBound(boolean bound, int memFactor, long now) {
- if (mActive <= 0) {
- throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
+ if (mOwner == null) {
+ Slog.wtf(TAG, "Binding service " + this + " without owner");
}
final int state = bound ? memFactor : STATE_NOTHING;
if (mBoundState != state) {
@@ -2949,8 +3065,8 @@
}
public void setExecuting(boolean executing, int memFactor, long now) {
- if (mActive <= 0) {
- throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
+ if (mOwner == null) {
+ Slog.wtf(TAG, "Executing service " + this + " without owner");
}
final int state = executing ? memFactor : STATE_NOTHING;
if (mExecState != state) {
@@ -2974,6 +3090,12 @@
}
return time;
}
+
+ public String toString() {
+ return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
+ + " " + mName + " pkg=" + mPackage + " proc="
+ + Integer.toHexString(System.identityHashCode(this)) + "}";
+ }
}
public static final class PackageState {
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
index 266ac98..7de0448 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
index 49b375f..5b916c9 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_grayedout_printer.png b/core/res/res/drawable-hdpi/ic_grayedout_printer.png
new file mode 100644
index 0000000..5e54970
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_grayedout_printer.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/overscroll_edge.png b/core/res/res/drawable-hdpi/overscroll_edge.png
index 08fc022..1952e0e 100644
--- a/core/res/res/drawable-hdpi/overscroll_edge.png
+++ b/core/res/res/drawable-hdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/overscroll_glow.png b/core/res/res/drawable-hdpi/overscroll_glow.png
index 8f0c2cb..45c0135 100644
--- a/core/res/res/drawable-hdpi/overscroll_glow.png
+++ b/core/res/res/drawable-hdpi/overscroll_glow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
index af5c463..eafc553 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
index 819c552..6583e99 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_grayedout_printer.png b/core/res/res/drawable-mdpi/ic_grayedout_printer.png
new file mode 100644
index 0000000..5e54970
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_grayedout_printer.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/overscroll_edge.png b/core/res/res/drawable-mdpi/overscroll_edge.png
index 4c87a8b..baf2d0c 100644
--- a/core/res/res/drawable-mdpi/overscroll_edge.png
+++ b/core/res/res/drawable-mdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/overscroll_glow.png b/core/res/res/drawable-mdpi/overscroll_glow.png
index 8389ef4..c6cddd4 100644
--- a/core/res/res/drawable-mdpi/overscroll_glow.png
+++ b/core/res/res/drawable-mdpi/overscroll_glow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
index 0e1b948..028eed6 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
index 8d8aabc..61efd3a 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_grayedout_printer.png b/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
new file mode 100644
index 0000000..5e54970
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/overscroll_edge.png b/core/res/res/drawable-xhdpi/overscroll_edge.png
index 4fe6c27..b5e6e61 100644
--- a/core/res/res/drawable-xhdpi/overscroll_edge.png
+++ b/core/res/res/drawable-xhdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/overscroll_glow.png b/core/res/res/drawable-xhdpi/overscroll_glow.png
index 75c3eb4..779c3a5 100644
--- a/core/res/res/drawable-xhdpi/overscroll_glow.png
+++ b/core/res/res/drawable-xhdpi/overscroll_glow.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
index 81b0f87..668548b 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/overscroll_edge.png b/core/res/res/drawable-xxhdpi/overscroll_edge.png
index 1a92737..734bfa7 100644
--- a/core/res/res/drawable-xxhdpi/overscroll_edge.png
+++ b/core/res/res/drawable-xxhdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/overscroll_glow.png b/core/res/res/drawable-xxhdpi/overscroll_glow.png
index c187e95..dc1f279 100644
--- a/core/res/res/drawable-xxhdpi/overscroll_glow.png
+++ b/core/res/res/drawable-xxhdpi/overscroll_glow.png
Binary files differ
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index 053fc85..dc90bbf 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -18,7 +18,5 @@
-->
<resources>
<integer name="kg_carousel_angle">75</integer>
- <integer name="kg_security_flip_duration">100</integer>
- <integer name="kg_security_fade_duration">100</integer>
<integer name="kg_glowpad_rotation_offset">0</integer>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 56e7ff9..d57c232 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4451,6 +4451,9 @@
<!-- Print fail reason: unknown. [CHAR LIMIT=25] -->
<string name="reason_unknown">unknown</string>
+ <!-- Print fail reason: the print service that has to process the print job is not available. [CHAR LIMIT=none] -->
+ <string name="reason_service_unavailable">Print service not enabled</string>
+
<!-- Title for the notification that a print service was installed. [CHAR LIMIT=50] -->
<string name="print_service_installed_title"><xliff:g id="name" example="Cloud Print">%s</xliff:g> service installed</string>
<!-- Message for the notification that a print service was installed. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7608f99..d483fe0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -928,6 +928,7 @@
<java-symbol type="string" name="mediasize_japanese_kahu" />
<java-symbol type="string" name="mediasize_japanese_kaku2" />
<java-symbol type="string" name="mediasize_japanese_you4" />
+ <java-symbol type="string" name="reason_service_unavailable" />
<java-symbol type="string" name="reason_unknown" />
<java-symbol type="string" name="restr_pin_enter_admin_pin" />
<java-symbol type="string" name="restr_pin_enter_pin" />
@@ -1041,6 +1042,7 @@
<java-symbol type="drawable" name="ic_text_dot" />
<java-symbol type="drawable" name="ic_print" />
<java-symbol type="drawable" name="ic_print_error" />
+ <java-symbol type="drawable" name="ic_grayedout_printer" />
<java-symbol type="drawable" name="indicator_code_lock_drag_direction_green_up" />
<java-symbol type="drawable" name="indicator_code_lock_drag_direction_red_up" />
<java-symbol type="drawable" name="indicator_code_lock_point_area_default_holo" />
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index e3a7e2b..8188782 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -202,7 +202,13 @@
public void setColorFilter(ColorFilter cf) {
mInsetState.mDrawable.setColorFilter(cf);
}
-
+
+ /** {@hide} */
+ @Override
+ public void setLayoutDirection(int layoutDirection) {
+ mInsetState.mDrawable.setLayoutDirection(layoutDirection);
+ }
+
@Override
public int getOpacity() {
return mInsetState.mDrawable.getOpacity();
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 720494b..ab34c0f 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -219,16 +219,15 @@
@Override
public void draw(Canvas canvas) {
final Rect bounds = getBounds();
- final boolean needMirroring = isAutoMirrored() &&
- getLayoutDirection() == LayoutDirection.RTL;
- if (needMirroring) {
+ final boolean needsMirroring = needsMirroring();
+ if (needsMirroring) {
canvas.save();
// Mirror the 9patch
canvas.translate(bounds.right - bounds.left, 0);
canvas.scale(-1.0f, 1.0f);
}
mNinePatch.draw(canvas, bounds, mPaint);
- if (needMirroring) {
+ if (needsMirroring) {
canvas.restore();
}
}
@@ -240,7 +239,11 @@
@Override
public boolean getPadding(Rect padding) {
- padding.set(mPadding);
+ if (needsMirroring()) {
+ padding.set(mPadding.right, mPadding.top, mPadding.left, mPadding.bottom);
+ } else {
+ padding.set(mPadding);
+ }
return true;
}
@@ -249,7 +252,12 @@
*/
@Override
public Insets getOpticalInsets() {
- return mOpticalInsets;
+ if (needsMirroring()) {
+ return Insets.of(mOpticalInsets.right, mOpticalInsets.top, mOpticalInsets.right,
+ mOpticalInsets.bottom);
+ } else {
+ return mOpticalInsets;
+ }
}
@Override
@@ -297,6 +305,10 @@
mNinePatchState.mAutoMirrored = mirrored;
}
+ private boolean needsMirroring() {
+ return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
+ }
+
@Override
public boolean isAutoMirrored() {
return mNinePatchState.mAutoMirrored;
diff --git a/packages/Keyguard/res/anim/keyguard_security_fade_in.xml b/packages/DocumentsUI/res/animator-ldrtl/dir_down.xml
similarity index 66%
rename from packages/Keyguard/res/anim/keyguard_security_fade_in.xml
rename to packages/DocumentsUI/res/animator-ldrtl/dir_down.xml
index c66c604..6c7e224 100644
--- a/packages/Keyguard/res/anim/keyguard_security_fade_in.xml
+++ b/packages/DocumentsUI/res/animator-ldrtl/dir_down.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- 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.
@@ -14,9 +13,10 @@
limitations under the License.
-->
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:interpolator/decelerate_quad"
- android:fromAlpha="0.0" android:toAlpha="1.0"
- android:duration="@integer/kg_security_fade_duration" />
-
-
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:valueFrom="-1"
+ android:valueTo="0"
+ android:propertyName="position"
+ android:valueType="floatType"
+ android:duration="@android:integer/config_mediumAnimTime"
+ android:interpolator="@android:interpolator/decelerate_quad" />
diff --git a/packages/Keyguard/res/anim/keyguard_security_fade_out.xml b/packages/DocumentsUI/res/animator-ldrtl/dir_up.xml
similarity index 66%
rename from packages/Keyguard/res/anim/keyguard_security_fade_out.xml
rename to packages/DocumentsUI/res/animator-ldrtl/dir_up.xml
index 6465b35..8e2925c 100644
--- a/packages/Keyguard/res/anim/keyguard_security_fade_out.xml
+++ b/packages/DocumentsUI/res/animator-ldrtl/dir_up.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- 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.
@@ -13,9 +12,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:interpolator/accelerate_quad"
- android:fromAlpha="1.0"
- android:toAlpha="0.0"
- android:duration="@integer/kg_security_fade_duration"
-/>
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:valueFrom="0"
+ android:valueTo="-1"
+ android:propertyName="position"
+ android:valueType="floatType"
+ android:duration="@android:integer/config_mediumAnimTime"
+ android:interpolator="@android:interpolator/accelerate_quad" />
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow.9.png b/packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow.9.png
rename to packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_drawer_shadow_tablet.9.png b/packages/DocumentsUI/res/drawable-hdpi/ic_drawer_shadow_tablet_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-hdpi/ic_drawer_shadow_tablet.9.png
rename to packages/DocumentsUI/res/drawable-hdpi/ic_drawer_shadow_tablet_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow.9.png b/packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow.9.png
rename to packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_drawer_shadow_tablet.9.png b/packages/DocumentsUI/res/drawable-mdpi/ic_drawer_shadow_tablet_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-mdpi/ic_drawer_shadow_tablet.9.png
rename to packages/DocumentsUI/res/drawable-mdpi/ic_drawer_shadow_tablet_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow.9.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow.9.png
rename to packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_shadow_tablet.9.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_shadow_tablet_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_shadow_tablet.9.png
rename to packages/DocumentsUI/res/drawable-xhdpi/ic_drawer_shadow_tablet_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow.9.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow.9.png
rename to packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_shadow_tablet.9.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_shadow_tablet_am.9.png
similarity index 100%
rename from packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_shadow_tablet.9.png
rename to packages/DocumentsUI/res/drawable-xxhdpi/ic_drawer_shadow_tablet_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable/ic_dir_shadow.xml b/packages/DocumentsUI/res/drawable/ic_dir_shadow.xml
new file mode 100644
index 0000000..1153e69
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_dir_shadow.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_dir_shadow_am"
+ android:autoMirrored="true">
+</nine-patch>
diff --git a/packages/DocumentsUI/res/drawable/ic_drawer_shadow_tablet.xml b/packages/DocumentsUI/res/drawable/ic_drawer_shadow_tablet.xml
new file mode 100644
index 0000000..382ebff
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_drawer_shadow_tablet.xml
@@ -0,0 +1,23 @@
+<?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.
+ */
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/ic_drawer_shadow_tablet_am"
+ android:autoMirrored="true">
+</nine-patch>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 23a3f22..22dd6e4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -69,7 +69,12 @@
@Override
public void onClick(DialogInterface dialog, int which) {
final String displayName = text1.getText().toString();
- new CreateDirectoryTask(displayName).execute();
+
+ final DocumentsActivity activity = (DocumentsActivity) getActivity();
+ final DocumentInfo cwd = activity.getCurrentDirectory();
+
+ new CreateDirectoryTask(displayName).executeOnExecutor(
+ ProviderExecutor.forAuthority(cwd.authority));
}
});
builder.setNegativeButton(android.R.string.cancel, null);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 6ff47f8..59caad0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -27,6 +27,7 @@
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
+import android.app.ActivityManager;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
@@ -113,6 +114,7 @@
private boolean mHideGridTitles = false;
+ private boolean mSvelteRecents;
private Point mThumbSize;
private DocumentsAdapter mAdapter;
@@ -204,6 +206,19 @@
}
@Override
+ public void onDestroyView() {
+ super.onDestroyView();
+
+ // Cancel any outstanding thumbnail requests
+ final ViewGroup target = (mListView.getAdapter() != null) ? mListView : mGridView;
+ final int count = target.getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View view = target.getChildAt(i);
+ mRecycleListener.onMovedToScrapHeap(view);
+ }
+ }
+
+ @Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -225,6 +240,10 @@
mHideGridTitles = (doc != null) && doc.isGridTitlesHidden();
}
+ final ActivityManager am = (ActivityManager) context.getSystemService(
+ Context.ACTIVITY_SERVICE);
+ mSvelteRecents = am.isLowRamDevice() && (mType == TYPE_RECENT_OPEN);
+
mCallbacks = new LoaderCallbacks<DirectoryResult>() {
@Override
public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
@@ -260,7 +279,7 @@
public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
if (!isAdded()) return;
- mAdapter.swapResult(result.cursor, result.exception);
+ mAdapter.swapResult(result);
// Push latest state up to UI
// TODO: if mode change was racing with us, don't overwrite it
@@ -286,7 +305,7 @@
@Override
public void onLoaderReset(Loader<DirectoryResult> loader) {
- mAdapter.swapResult(null, null);
+ mAdapter.swapResult(null);
}
};
@@ -654,13 +673,13 @@
private List<Footer> mFooters = Lists.newArrayList();
- public void swapResult(Cursor cursor, Exception e) {
- mCursor = cursor;
- mCursorCount = cursor != null ? cursor.getCount() : 0;
+ public void swapResult(DirectoryResult result) {
+ mCursor = result != null ? result.cursor : null;
+ mCursorCount = mCursor != null ? mCursor.getCount() : 0;
mFooters.clear();
- final Bundle extras = cursor != null ? cursor.getExtras() : null;
+ final Bundle extras = mCursor != null ? mCursor.getExtras() : null;
if (extras != null) {
final String info = extras.getString(DocumentsContract.EXTRA_INFO);
if (info != null) {
@@ -675,7 +694,7 @@
}
}
- if (e != null) {
+ if (result != null && result.exception != null) {
mFooters.add(new MessageFooter(
3, R.drawable.ic_dialog_alert, getString(R.string.query_error)));
}
@@ -776,7 +795,7 @@
final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
|| MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, docMimeType);
- final boolean showThumbnail = supportsThumbnail && allowThumbnail;
+ final boolean showThumbnail = supportsThumbnail && allowThumbnail && !mSvelteRecents;
boolean cacheHit = false;
if (showThumbnail) {
@@ -790,7 +809,7 @@
final ThumbnailAsyncTask task = new ThumbnailAsyncTask(
uri, iconMime, iconThumb, mThumbSize);
iconThumb.setTag(task);
- task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ task.executeOnExecutor(ProviderExecutor.forAuthority(docAuthority));
}
}
@@ -983,6 +1002,8 @@
@Override
protected Bitmap doInBackground(Uri... params) {
+ if (isCancelled()) return null;
+
final Context context = mIconThumb.getContext();
final ContentResolver resolver = context.getContentResolver();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index da0f526..163615d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -79,7 +79,7 @@
public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
int userSortOrder) {
- super(context);
+ super(context, ProviderExecutor.forAuthority(root.authority));
mType = type;
mRoot = root;
mDoc = doc;
@@ -157,11 +157,11 @@
Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
+ result.mode + ", sortOrder=" + result.sortOrder);
+ ContentProviderClient client = null;
try {
- result.client = DocumentsApplication.acquireUnstableProviderOrThrow(
- resolver, authority);
+ client = DocumentsApplication.acquireUnstableProviderOrThrow(resolver, authority);
- cursor = result.client.query(
+ cursor = client.query(
mUri, null, null, null, getQuerySortOrder(result.sortOrder), mSignal);
cursor.registerContentObserver(mObserver);
@@ -175,11 +175,12 @@
cursor = new SortingCursorWrapper(cursor, result.sortOrder);
}
+ result.client = client;
result.cursor = cursor;
} catch (Exception e) {
Log.w(TAG, "Failed to query", e);
result.exception = e;
- ContentProviderClient.releaseQuietly(result.client);
+ ContentProviderClient.releaseQuietly(client);
} finally {
synchronized (this) {
mSignal = null;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
index 28e2bd9..b552e5a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
@@ -40,7 +40,7 @@
public void setBackground(Drawable background) {
final Rect rect = new Rect();
background.getPadding(rect);
- final InsetDrawable inset = new InsetDrawable(background, -rect.left, 0, 0, 0);
+ final InsetDrawable inset = new InsetDrawable(background, -rect.left, 0, -rect.right, 0);
super.setBackground(inset);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 7a45641..7660779 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -91,6 +91,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.Executor;
public class DocumentsActivity extends Activity {
public static final String TAG = "Documents";
@@ -215,7 +216,7 @@
if (!mState.restored) {
if (mState.action == ACTION_MANAGE) {
final Uri rootUri = getIntent().getData();
- new RestoreRootTask(rootUri).execute();
+ new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
} else {
new RestoreStackTask().execute();
}
@@ -782,6 +783,15 @@
return mState.stack.peek();
}
+ public Executor getCurrentExecutor() {
+ final DocumentInfo cwd = getCurrentDirectory();
+ if (cwd != null && cwd.authority != null) {
+ return ProviderExecutor.forAuthority(cwd.authority);
+ } else {
+ return AsyncTask.THREAD_POOL_EXECUTOR;
+ }
+ }
+
public State getDisplayState() {
return mState;
}
@@ -855,7 +865,7 @@
mState.stackTouched = true;
if (!mRoots.isRecentsRoot(root)) {
- new PickRootTask(root).execute();
+ new PickRootTask(root).executeOnExecutor(getCurrentExecutor());
} else {
onCurrentDirectoryChanged(ANIM_SIDE);
}
@@ -932,7 +942,7 @@
onCurrentDirectoryChanged(ANIM_DOWN);
} else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
// Explicit file picked, return
- new ExistingFinishTask(doc.derivedUri).execute();
+ new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getCurrentExecutor());
} else if (mState.action == ACTION_CREATE) {
// Replace selected file
SaveFragment.get(fm).setReplaceTarget(doc);
@@ -966,16 +976,16 @@
for (int i = 0; i < size; i++) {
uris[i] = docs.get(i).derivedUri;
}
- new ExistingFinishTask(uris).execute();
+ new ExistingFinishTask(uris).executeOnExecutor(getCurrentExecutor());
}
}
public void onSaveRequested(DocumentInfo replaceTarget) {
- new ExistingFinishTask(replaceTarget.derivedUri).execute();
+ new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getCurrentExecutor());
}
public void onSaveRequested(String mimeType, String displayName) {
- new CreateFinishTask(mimeType, displayName).execute();
+ new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
}
private void saveStackBlocking() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
new file mode 100644
index 0000000..2105cb41
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+package com.android.documentsui;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.google.android.collect.Maps;
+
+import java.util.HashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class ProviderExecutor extends Thread implements Executor {
+
+ @GuardedBy("sExecutors")
+ private static HashMap<String, ProviderExecutor> sExecutors = Maps.newHashMap();
+
+ public static Executor forAuthority(String authority) {
+ synchronized (sExecutors) {
+ ProviderExecutor executor = sExecutors.get(authority);
+ if (executor == null) {
+ executor = new ProviderExecutor();
+ executor.setName("ProviderExecutor: " + authority);
+ executor.start();
+ sExecutors.put(authority, executor);
+ }
+ return executor;
+ }
+ }
+
+ private final LinkedBlockingQueue<Runnable> mQueue = new LinkedBlockingQueue<Runnable>();
+
+ @Override
+ public void execute(Runnable command) {
+ Preconditions.checkNotNull(command);
+ mQueue.add(command);
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ final Runnable command = mQueue.take();
+ command.run();
+ } catch (InterruptedException e) {
+ // That was weird; let's go look for more tasks.
+ }
+ }
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index 47dbcdf..3a8a3fb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -49,9 +49,7 @@
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
@@ -74,30 +72,7 @@
/** MIME types that should always be excluded from recents. */
private static final String[] RECENT_REJECT_MIMES = new String[] { Document.MIME_TYPE_DIR };
- private static ExecutorService sExecutor;
-
- /**
- * Create a bounded thread pool for fetching recents; it creates threads as
- * needed (up to maximum) and reclaims them when finished.
- */
- private synchronized static ExecutorService getExecutor(Context context) {
- if (sExecutor == null) {
- final ActivityManager am = (ActivityManager) context.getSystemService(
- Context.ACTIVITY_SERVICE);
- final int maxOutstanding = am.isLowRamDevice() ? MAX_OUTSTANDING_RECENTS_SVELTE
- : MAX_OUTSTANDING_RECENTS;
-
- // Create a bounded thread pool for fetching recents; it creates
- // threads as needed (up to maximum) and reclaims them when finished.
- final ThreadPoolExecutor executor = new ThreadPoolExecutor(
- maxOutstanding, maxOutstanding, 10, TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>());
- executor.allowCoreThreadTimeOut(true);
- sExecutor = executor;
- }
-
- return sExecutor;
- }
+ private final Semaphore mQueryPermits;
private final RootsCache mRoots;
private final State mState;
@@ -129,6 +104,20 @@
public void run() {
if (isCancelled()) return;
+ try {
+ mQueryPermits.acquire();
+ } catch (InterruptedException e) {
+ return;
+ }
+
+ try {
+ runInternal();
+ } finally {
+ mQueryPermits.release();
+ }
+ }
+
+ public void runInternal() {
ContentProviderClient client = null;
try {
client = DocumentsApplication.acquireUnstableProviderOrThrow(
@@ -138,6 +127,7 @@
final Cursor cursor = client.query(
uri, null, null, null, DirectoryLoader.getQuerySortOrder(mSortOrder));
mWithRoot = new RootCursorWrapper(authority, rootId, cursor, MAX_DOCS_FROM_ROOT);
+
} catch (Exception e) {
Log.w(TAG, "Failed to load " + authority + ", " + rootId, e);
} finally {
@@ -162,12 +152,17 @@
super(context);
mRoots = roots;
mState = state;
+
+ // Keep clients around on high-RAM devices, since we'd be spinning them
+ // up moments later to fetch thumbnails anyway.
+ final ActivityManager am = (ActivityManager) getContext().getSystemService(
+ Context.ACTIVITY_SERVICE);
+ mQueryPermits = new Semaphore(
+ am.isLowRamDevice() ? MAX_OUTSTANDING_RECENTS_SVELTE : MAX_OUTSTANDING_RECENTS);
}
@Override
public DirectoryResult loadInBackground() {
- final ExecutorService executor = getExecutor(getContext());
-
if (mFirstPassLatch == null) {
// First time through we kick off all the recent tasks, and wait
// around to see if everyone finishes quickly.
@@ -182,7 +177,7 @@
mFirstPassLatch = new CountDownLatch(mTasks.size());
for (RecentTask task : mTasks.values()) {
- executor.execute(task);
+ ProviderExecutor.forAuthority(task.authority).execute(task);
}
try {
@@ -224,7 +219,6 @@
if (LOGD) {
Log.d(TAG, "Found " + cursors.size() + " of " + mTasks.size() + " recent queries done");
- Log.d(TAG, executor.toString());
}
final DirectoryResult result = new DirectoryResult();
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
index e9f2c71..0caddcc 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
@@ -66,6 +66,7 @@
private static final boolean CHILD_WEDGE = false;
private static final boolean CHILD_CRASH = false;
+ private static final boolean THUMB_HUNDREDS = false;
private static final boolean THUMB_WEDGE = false;
private static final boolean THUMB_CRASH = false;
@@ -225,6 +226,12 @@
includeFile(result, "localfile3", 0);
includeFile(result, "localfile4", 0);
+ if (THUMB_HUNDREDS) {
+ for (int i = 0; i < 256; i++) {
+ includeFile(result, "i maded u an picshure", Document.FLAG_SUPPORTS_THUMBNAIL);
+ }
+ }
+
synchronized (this) {
// Try picking up an existing network fetch
CloudTask task = mTask != null ? mTask.get() : null;
@@ -292,7 +299,7 @@
public AssetFileDescriptor openDocumentThumbnail(
String docId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
- if (THUMB_WEDGE) SystemClock.sleep(Integer.MAX_VALUE);
+ if (THUMB_WEDGE) wedgeUntilCanceled(signal);
if (THUMB_CRASH) System.exit(12);
final Bitmap bitmap = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888);
@@ -332,6 +339,18 @@
return true;
}
+ private static void wedgeUntilCanceled(CancellationSignal signal) {
+ if (signal != null) {
+ while (true) {
+ signal.throwIfCanceled();
+ SystemClock.sleep(500);
+ }
+ } else {
+ Log.w(TAG, "WEDGING WITHOUT A CANCELLATIONSIGNAL");
+ SystemClock.sleep(Integer.MAX_VALUE);
+ }
+ }
+
private static void includeFile(MatrixCursor result, String docId, int flags) {
final RowBuilder row = result.newRow();
row.add(Document.COLUMN_DOCUMENT_ID, docId);
diff --git a/packages/Keyguard/res/anim/keyguard_security_animate_in.xml b/packages/Keyguard/res/anim/keyguard_security_animate_in.xml
deleted file mode 100644
index 4ee30c3..0000000
--- a/packages/Keyguard/res/anim/keyguard_security_animate_in.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-
- <scale
- android:interpolator="@android:anim/decelerate_interpolator"
- android:fromXScale="0.0"
- android:toXScale="1.0"
- android:fromYScale="1.0"
- android:toYScale="1.0"
- android:pivotX="50%"
- android:pivotY="50%"
- android:fillEnabled="true"
- android:fillAfter="true"
- android:duration="@integer/kg_security_flip_duration"
- android:startOffset="@integer/kg_security_flip_duration" />
-
-</set>
-
diff --git a/packages/Keyguard/res/anim/keyguard_security_animate_out.xml b/packages/Keyguard/res/anim/keyguard_security_animate_out.xml
deleted file mode 100644
index 76d065c..0000000
--- a/packages/Keyguard/res/anim/keyguard_security_animate_out.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-
- <scale
- android:interpolator="@android:anim/accelerate_interpolator"
- android:fromXScale="1.0"
- android:toXScale="0.0"
- android:fromYScale="1.0"
- android:toYScale="1.0"
- android:pivotX="50%"
- android:pivotY="50%"
- android:fillEnabled="true"
- android:fillAfter="true"
- android:duration="@integer/kg_security_flip_duration" />
-
-</set>
-
diff --git a/packages/Keyguard/res/values/integers.xml b/packages/Keyguard/res/values/integers.xml
index 053fc85..dc90bbf 100644
--- a/packages/Keyguard/res/values/integers.xml
+++ b/packages/Keyguard/res/values/integers.xml
@@ -18,7 +18,5 @@
-->
<resources>
<integer name="kg_carousel_angle">75</integer>
- <integer name="kg_security_flip_duration">100</integer>
- <integer name="kg_security_fade_duration">100</integer>
<integer name="kg_glowpad_rotation_offset">0</integer>
</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 4da6171..bc8c866 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -54,10 +54,10 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
-import android.view.animation.AnimationUtils;
import android.widget.RemoteViews.OnClickHandler;
import java.io.File;
+import java.lang.ref.WeakReference;
import java.util.List;
public class KeyguardHostView extends KeyguardViewBase {
@@ -125,6 +125,8 @@
private final Rect mInsets = new Rect();
+ private MyOnClickHandler mOnClickHandler = new MyOnClickHandler(this);
+
/*package*/ interface UserSwitcherCallback {
void hideSecurityView(int duration);
void showSecurityView();
@@ -813,24 +815,39 @@
}
}
- private OnClickHandler mOnClickHandler = new OnClickHandler() {
+ private static class MyOnClickHandler extends OnClickHandler {
+
+ // weak reference to the hostView to avoid keeping a live reference
+ // due to Binder GC linkages to AppWidgetHost. By the same token,
+ // this click handler should not keep references to any large
+ // objects.
+ WeakReference<KeyguardHostView> mThis;
+
+ MyOnClickHandler(KeyguardHostView hostView) {
+ mThis = new WeakReference<KeyguardHostView>(hostView);
+ }
+
@Override
public boolean onClickHandler(final View view,
final android.app.PendingIntent pendingIntent,
final Intent fillInIntent) {
+ KeyguardHostView hostView = mThis.get();
+ if (hostView == null) {
+ return false;
+ }
if (pendingIntent.isActivity()) {
- setOnDismissAction(new OnDismissAction() {
+ hostView.setOnDismissAction(new OnDismissAction() {
public boolean onDismiss() {
try {
- // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
- Context context = view.getContext();
- ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
- 0, 0,
- view.getMeasuredWidth(), view.getMeasuredHeight());
- context.startIntentSender(
- pendingIntent.getIntentSender(), fillInIntent,
- Intent.FLAG_ACTIVITY_NEW_TASK,
- Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
+ // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
+ Context context = view.getContext();
+ ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
+ 0, 0,
+ view.getMeasuredWidth(), view.getMeasuredHeight());
+ context.startIntentSender(
+ pendingIntent.getIntentSender(), fillInIntent,
+ Intent.FLAG_ACTIVITY_NEW_TASK,
+ Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
} catch (IntentSender.SendIntentException e) {
android.util.Log.e(TAG, "Cannot send pending intent: ", e);
} catch (Exception e) {
@@ -841,10 +858,10 @@
}
});
- if (mViewStateManager.isChallengeShowing()) {
- mViewStateManager.showBouncer(true);
+ if (hostView.mViewStateManager.isChallengeShowing()) {
+ hostView.mViewStateManager.showBouncer(true);
} else {
- mCallback.dismiss(false);
+ hostView.mCallback.dismiss(false);
}
return true;
} else {
@@ -971,10 +988,6 @@
// Find and show this child.
final int childCount = mSecurityViewContainer.getChildCount();
- mSecurityViewContainer.setInAnimation(
- AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
- mSecurityViewContainer.setOutAnimation(
- AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
for (int i = 0; i < childCount; i++) {
if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index f4e1853..e86e9aa 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ android:layout_height="fill_parent">
<fragment
android:name="com.android.printspooler.SelectPrinterFragment"
@@ -26,4 +26,39 @@
android:layout_height="wrap_content">
</fragment>
-</FrameLayout>
\ No newline at end of file
+ <FrameLayout
+ android:id="@+id/empty_print_state"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:visibility="gone">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dip"
+ android:src="@*android:drawable/ic_grayedout_printer"
+ android:contentDescription="@string/print_no_printers_found">
+ </ImageView>
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/print_no_printers_found">
+ </TextView>
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 5ee8d8c..41775a1 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -75,13 +75,16 @@
<!-- Title for the select printer activity. [CHAR LIMIT=30] -->
<string name="all_printers_label">All printers</string>
+ <!-- Title of the button to install a print service. [CHAR LIMIT=25] -->
+ <string name="add_print_service_label">Add service</string>
+
<!-- Add printer dialog -->
<!-- Title for the alert dialog for selecting a print service. [CHAR LIMIT=50] -->
<string name="choose_print_service">Choose print service</string>
- <!-- Title for the button to search the play store for print services. [CHAR LIMIT=50] -->
- <string name="search_play_store">Search in play store</string>
+ <!-- Title for the prompt shown as a placeholder if no printers are found while searching. [CHAR LIMIT=50] -->
+ <string name="print_no_printers_found">No printers found</string>
<!-- Notifications -->
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
index c397c40..c888e2c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
@@ -92,6 +92,8 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(new DestinationAdapter());
+ View emptyView = getActivity().findViewById(R.id.empty_print_state);
+ getListView().setEmptyView(emptyView);
}
@Override
@@ -252,7 +254,7 @@
Uri marketUri = Uri.parse(DEFAULT_MARKET_QUERY_STRING);
final Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
if (getActivity().getPackageManager().resolveActivity(marketIntent, 0) != null) {
- builder.setPositiveButton(R.string.search_play_store,
+ builder.setPositiveButton(R.string.add_print_service_label,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
try {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index a5fd1d7..7f93c28 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1621,7 +1621,7 @@
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
if (!compatInfo.supportsScreen()) {
- win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
+ win.addFlags(WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW);
}
win.setDefaultIcon(icon);
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index 0bf03b5..069ae23 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -122,7 +122,9 @@
try {
return super.onTransact(code, data, reply, flags);
} catch (RuntimeException e) {
- Slog.w("clipboard", "Exception: ", e);
+ if (!(e instanceof SecurityException)) {
+ Slog.wtf("clipboard", "Exception: ", e);
+ }
throw e;
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 45c614f..794d274 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -817,7 +817,7 @@
// The input method manager only throws security exceptions, so let's
// log all others.
if (!(e instanceof SecurityException)) {
- Slog.e(TAG, "Input Method Manager Crash", e);
+ Slog.wtf(TAG, "Input Method Manager Crash", e);
}
throw e;
}
diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java
index 3a3dfd5..dd9ae4c 100644
--- a/services/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/java/com/android/server/accounts/AccountManagerService.java
@@ -60,6 +60,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -267,6 +268,21 @@
}, UserHandle.ALL, userFilter, null, null);
}
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (RuntimeException e) {
+ // The account manager only throws security exceptions, so let's
+ // log all others.
+ if (!(e instanceof SecurityException)) {
+ Slog.wtf(TAG, "Account Manager Crash", e);
+ }
+ throw e;
+ }
+ }
+
public void systemReady() {
}
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index fa1769f..27ca7a0 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -130,9 +130,9 @@
= new ArrayList<ServiceRecord>();
/**
- * List of services that are in the process of being stopped.
+ * List of services that are in the process of being destroyed.
*/
- final ArrayList<ServiceRecord> mStoppingServices
+ final ArrayList<ServiceRecord> mDestroyingServices
= new ArrayList<ServiceRecord>();
static final class DelayingProcess extends ArrayList<ServiceRecord> {
@@ -788,7 +788,7 @@
}
}
- serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
+ serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -834,9 +834,9 @@
+ " at " + b + ": apps="
+ (b != null ? b.apps.size() : 0));
- boolean inStopping = mStoppingServices.contains(r);
+ boolean inDestroying = mDestroyingServices.contains(r);
if (b != null) {
- if (b.apps.size() > 0 && !inStopping) {
+ if (b.apps.size() > 0 && !inDestroying) {
// Applications have already bound since the last
// unbind, so just rebind right here.
boolean inFg = false;
@@ -856,7 +856,7 @@
}
}
- serviceDoneExecutingLocked(r, inStopping);
+ serviceDoneExecutingLocked(r, inDestroying, false);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -1419,14 +1419,10 @@
}
}
- private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
- boolean hasConn) {
- //Slog.i(TAG, "Bring down service:");
- //r.dump(" ");
-
+ private final boolean isServiceNeeded(ServiceRecord r, boolean knowConn, boolean hasConn) {
// Are we still explicitly being asked to run?
if (r.startRequested) {
- return;
+ return true;
}
// Is someone still bound to us keepign us running?
@@ -1434,6 +1430,18 @@
hasConn = r.hasAutoCreateConnections();
}
if (hasConn) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
+ boolean hasConn) {
+ //Slog.i(TAG, "Bring down service:");
+ //r.dump(" ");
+
+ if (isServiceNeeded(r, knowConn, hasConn)) {
return;
}
@@ -1484,7 +1492,7 @@
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service "
+ r.shortName, e);
- serviceDoneExecutingLocked(r, true);
+ serviceDoneExecutingLocked(r, true, true);
}
}
}
@@ -1527,14 +1535,14 @@
r.app.services.remove(r);
if (r.app.thread != null) {
try {
- bumpServiceExecutingLocked(r, false, "stop");
- mStoppingServices.add(r);
+ bumpServiceExecutingLocked(r, false, "destroy");
+ mDestroyingServices.add(r);
mAm.updateOomAdjLocked(r.app);
r.app.thread.scheduleStopService(r);
} catch (Exception e) {
- Slog.w(TAG, "Exception when stopping service "
+ Slog.w(TAG, "Exception when destroying service "
+ r.shortName, e);
- serviceDoneExecutingLocked(r, true);
+ serviceDoneExecutingLocked(r, true, true);
}
updateServiceForegroundLocked(r.app, false);
} else {
@@ -1560,7 +1568,7 @@
r.tracker.setStarted(false, memFactor, now);
r.tracker.setBound(false, memFactor, now);
if (r.executeNesting == 0) {
- r.tracker.makeInactive();
+ r.tracker.clearCurrentOwner(r);
r.tracker = null;
}
}
@@ -1619,7 +1627,7 @@
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
- serviceDoneExecutingLocked(s, true);
+ serviceDoneExecutingLocked(s, true, true);
}
}
@@ -1637,7 +1645,7 @@
}
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
- boolean inStopping = mStoppingServices.contains(r);
+ boolean inDestroying = mDestroyingServices.contains(r);
if (r != null) {
if (type == 1) {
// This is a call from a service start... take care of
@@ -1690,7 +1698,7 @@
}
}
final long origId = Binder.clearCallingIdentity();
- serviceDoneExecutingLocked(r, inStopping);
+ serviceDoneExecutingLocked(r, inDestroying, inDestroying);
Binder.restoreCallingIdentity(origId);
} else {
Slog.w(TAG, "Done executing unknown service from pid "
@@ -1698,10 +1706,11 @@
}
}
- private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
+ private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
+ boolean finishing) {
if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+ ": nesting=" + r.executeNesting
- + ", inStopping=" + inStopping + ", app=" + r.app);
+ + ", inDestroying=" + inDestroying + ", app=" + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
r.executeNesting--;
if (r.executeNesting <= 0) {
@@ -1723,10 +1732,10 @@
}
}
}
- if (inStopping) {
+ if (inDestroying) {
if (DEBUG_SERVICE) Slog.v(TAG,
- "doneExecuting remove stopping " + r);
- mStoppingServices.remove(r);
+ "doneExecuting remove destroying " + r);
+ mDestroyingServices.remove(r);
r.bindings.clear();
}
mAm.updateOomAdjLocked(r.app);
@@ -1735,8 +1744,8 @@
if (r.tracker != null) {
r.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
- if (inStopping) {
- r.tracker.makeInactive();
+ if (finishing) {
+ r.tracker.clearCurrentOwner(r);
r.tracker = null;
}
}
@@ -1839,7 +1848,7 @@
}
}
} else {
- ServiceMap smap = mServiceMap.valueAt(userId);
+ ServiceMap smap = mServiceMap.get(userId);
if (smap != null) {
ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
@@ -1931,12 +1940,9 @@
sr.app = null;
sr.isolatedProc = null;
sr.executeNesting = 0;
- if (sr.tracker != null) {
- sr.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
- }
- if (mStoppingServices.remove(sr)) {
- if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+ sr.forceClearTracker();
+ if (mDestroyingServices.remove(sr)) {
+ if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr);
}
final int numClients = sr.bindings.size();
@@ -1984,13 +1990,14 @@
}
// Make sure we have no more records on the stopping list.
- int i = mStoppingServices.size();
+ int i = mDestroyingServices.size();
while (i > 0) {
i--;
- ServiceRecord sr = mStoppingServices.get(i);
+ ServiceRecord sr = mDestroyingServices.get(i);
if (sr.app == app) {
- mStoppingServices.remove(i);
- if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+ sr.forceClearTracker();
+ mDestroyingServices.remove(i);
+ if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr);
}
}
@@ -2340,10 +2347,10 @@
needSep = true;
}
- if (mStoppingServices.size() > 0) {
+ if (mDestroyingServices.size() > 0) {
boolean printed = false;
- for (int i=0; i<mStoppingServices.size(); i++) {
- ServiceRecord r = mStoppingServices.get(i);
+ for (int i=0; i< mDestroyingServices.size(); i++) {
+ ServiceRecord r = mDestroyingServices.get(i);
if (!matcher.match(r, r.name)) {
continue;
}
@@ -2354,10 +2361,10 @@
if (!printed) {
if (needSep) pw.println();
needSep = true;
- pw.println(" Stopping services:");
+ pw.println(" Destroying services:");
printed = true;
}
- pw.print(" * Stopping "); pw.println(r);
+ pw.print(" * Destroy "); pw.println(r);
r.dump(pw, " ");
}
needSep = true;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c1ac7d5..f2ff9ca 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2051,7 +2051,7 @@
// The activity manager only throws security exceptions, so let's
// log all others.
if (!(e instanceof SecurityException)) {
- Slog.e(TAG, "Activity Manager Crash", e);
+ Slog.wtf(TAG, "Activity Manager Crash", e);
}
throw e;
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4d66946..28c87d1 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -978,7 +978,7 @@
*/
final boolean ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
String onlyThisProcess, int configChanges, boolean forceHomeShown) {
- if (DEBUG_VISBILITY) Slog.v(
+ if (true || DEBUG_VISBILITY) Slog.v(
TAG, "ensureActivitiesVisible behind " + top
+ " configChanges=0x" + Integer.toHexString(configChanges));
@@ -1034,7 +1034,7 @@
r.startFreezingScreenLocked(r.app, configChanges);
}
if (!r.visible) {
- if (DEBUG_VISBILITY) Slog.v(
+ if (true || DEBUG_VISBILITY) Slog.v(
TAG, "Starting and making visible: " + r);
mWindowManager.setAppVisibility(r.appToken, true);
}
@@ -1056,7 +1056,7 @@
if (r.state != ActivityState.RESUMED && r != starting) {
// If this activity is paused, tell it
// to now show its window.
- if (DEBUG_VISBILITY) Slog.v(
+ if (true || DEBUG_VISBILITY) Slog.v(
TAG, "Making visible and scheduling visibility: " + r);
try {
if (mTranslucentActivityWaiting != null) {
@@ -1110,7 +1110,7 @@
// Now for any activities that aren't visible to the user, make
// sure they no longer are keeping the screen frozen.
if (r.visible) {
- if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
+ if (true || DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
r.visible = false;
try {
mWindowManager.setAppVisibility(r.appToken, false);
@@ -2367,7 +2367,7 @@
if (mResumedActivity == r) {
boolean endTask = index <= 0;
- if (DEBUG_TRANSITION) Slog.v(TAG,
+ if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
"Prepare close transition: finishing " + r);
mWindowManager.prepareAppTransition(endTask
? AppTransition.TRANSIT_TASK_CLOSE
@@ -3438,23 +3438,22 @@
// Determine if the top task is exiting and should return to home. Do this before it gets
// removed in removeHistoryRecordsForAppsLocked.
boolean launchHomeNext = false;
- int top = mTaskHistory.size() - 1;
- while (top >= 0) {
- final TaskRecord topTask = mTaskHistory.get(top);
- if (topTask.mActivities.isEmpty()) {
- // Not possible, but just in case.
- --top;
+ TaskRecord topTask = mTaskHistory.get(mTaskHistory.size() - 1);
+ ArrayList<ActivityRecord> activities = topTask.mActivities;
+ int activityNdx;
+ for (activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ ActivityRecord r = activities.get(activityNdx);
+ if (r.finishing) {
continue;
}
- ActivityRecord r = topTask.topRunningActivityLocked(null);
- if (r != null) {
- // r will be launched next.
+ if (r.app != app) {
+ // This is the dying activity.
break;
}
- // There is an activity in topTask that is finishing. If topTask belongs to the app
- // return to home depending on the task flag.
+ }
+ if (activityNdx < 0) {
+ // All activities in task belong to app. Set launchHomeNext to task's value.
launchHomeNext = topTask.mOnTopOfHome;
- break;
}
removeHistoryRecordsForAppLocked(app);
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index f718706..2b69a4e 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -884,6 +884,7 @@
throws RemoteException {
r.startFreezingScreenLocked(app, 0);
+ if (true) Slog.d(TAG, "realStartActivity: setting app visibility true");
mWindowManager.setAppVisibility(r.appToken, true);
// schedule launch ticks to collect information about slow apps.
@@ -1932,7 +1933,7 @@
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
// Only update launchHomeTaskNext for the focused stack.
- launchHomeTaskNext |= (stack == focusedStack && stack.handleAppDiedLocked(app));
+ launchHomeTaskNext |= (stack.handleAppDiedLocked(app) && stack == focusedStack);
}
if (!restarting) {
@@ -2299,7 +2300,7 @@
final boolean nowVisible = allResumedActivitiesVisible();
for (int i=0; i<N; i++) {
ActivityRecord s = mStoppingActivities.get(i);
- if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
+ if (true || localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
+ nowVisible + " waitingVisible=" + s.waitingVisible
+ " finishing=" + s.finishing);
if (s.waitingVisible && nowVisible) {
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index bfc86b0..fffa75e 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -16,7 +16,7 @@
package com.android.server.am;
-import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import android.content.Context;
import android.content.DialogInterface;
@@ -72,7 +72,7 @@
}
setTitle(res.getText(com.android.internal.R.string.aerr_title));
- getWindow().addFlags(FLAG_SYSTEM_ERROR);
+ getWindow().addFlags(PRIVATE_FLAG_SYSTEM_ERROR);
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.setTitle("Application Error: " + app.info.processName);
attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index d0a0441..4de272d 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -16,7 +16,7 @@
package com.android.server.am;
-import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -94,7 +94,7 @@
if (aboveSystem) {
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
}
- getWindow().addFlags(FLAG_SYSTEM_ERROR);
+ getWindow().addFlags(PRIVATE_FLAG_SYSTEM_ERROR);
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.setTitle("Application Not Responding: " + app.info.processName);
attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 2c49bb9..7dc006c 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -357,7 +357,7 @@
boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
boolean sepProcStates, int[] procStates, long now, String reqPackage) {
ArrayList<ProcessStats.ProcessState> procs = mProcessStats.collectProcessesLocked(
- screenStates, memStates, procStates, procStates, now, reqPackage);
+ screenStates, memStates, procStates, procStates, now, reqPackage, false);
if (procs.size() > 0) {
if (header != null) {
pw.println(header);
@@ -519,7 +519,7 @@
static private void dumpHelp(PrintWriter pw) {
pw.println("Process stats (procstats) dump options:");
pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
- pw.println(" [--details] [--full-details] [--current] [--hours]");
+ pw.println(" [--details] [--full-details] [--current] [--hours] [--active]");
pw.println(" [--commit] [--reset] [--clear] [--write] [-h] [<package.name>]");
pw.println(" --checkin: perform a checkin: print and delete old committed states.");
pw.println(" --c: print only state in checkin format.");
@@ -528,10 +528,11 @@
pw.println(" --csv-mem: norm, mod, low, crit.");
pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,");
pw.println(" service, home, prev, cached");
- pw.println(" --details: dump all execution details, not just summary.");
- pw.println(" --full-details: dump only detail information, for all saved state.");
+ pw.println(" --details: dump per-package details, not just summary.");
+ pw.println(" --full-details: dump all timing and active state details.");
pw.println(" --current: only dump current state.");
pw.println(" --hours: aggregate over about N last hours.");
+ pw.println(" --active: only show currently active processes/services.");
pw.println(" --commit: commit current stats to disk and reset to start new stats.");
pw.println(" --reset: reset current stats, without committing.");
pw.println(" --clear: clear all stats; does both --reset and deletes old stats.");
@@ -562,6 +563,7 @@
boolean dumpFullDetails = false;
boolean dumpAll = false;
int aggregateHours = 0;
+ boolean activeOnly = false;
String reqPackage = null;
boolean csvSepScreenStats = false;
int[] csvScreenStats = new int[] { ProcessStats.ADJ_SCREEN_OFF, ProcessStats.ADJ_SCREEN_ON};
@@ -645,6 +647,9 @@
dumpHelp(pw);
return;
}
+ } else if ("--active".equals(arg)) {
+ activeOnly = true;
+ currentOnly = true;
} else if ("--current".equals(arg)) {
currentOnly = true;
} else if ("--commit".equals(arg)) {
@@ -779,9 +784,9 @@
stats.dumpCheckinLocked(pw, reqPackage);
} else {
if (dumpDetails || dumpFullDetails) {
- stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll);
+ stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
} else {
- stats.dumpSummaryLocked(pw, reqPackage, now);
+ stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
}
}
return;
@@ -826,9 +831,10 @@
// Always dump summary here, dumping all details is just too
// much crud.
if (dumpFullDetails) {
- mProcessStats.dumpLocked(pw, reqPackage, now, false, false);
+ mProcessStats.dumpLocked(pw, reqPackage, now, false, false,
+ activeOnly);
} else {
- processStats.dumpSummaryLocked(pw, reqPackage, now);
+ processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
}
}
if (isCheckin) {
@@ -856,12 +862,13 @@
pw.println("CURRENT STATS:");
}
if (dumpDetails || dumpFullDetails) {
- mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll);
+ mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
+ activeOnly);
if (dumpAll) {
pw.print(" mFile="); pw.println(mFile.getBaseFile());
}
} else {
- mProcessStats.dumpSummaryLocked(pw, reqPackage, now);
+ mProcessStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
}
}
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index ac14da9..c47c1ac 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -328,11 +328,23 @@
if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name);
- tracker.makeActive();
+ tracker.applyNewOwner(this);
}
return tracker;
}
+ public void forceClearTracker() {
+ if (tracker != null) {
+ int memFactor = ams.mProcessStats.getMemFactorLocked();
+ long now = SystemClock.uptimeMillis();
+ tracker.setStarted(false, memFactor, now);
+ tracker.setBound(false, memFactor, now);
+ tracker.setExecuting(false, memFactor, now);
+ tracker.clearCurrentOwner(this);
+ tracker = null;
+ }
+ }
+
public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
diff --git a/services/java/com/android/server/am/StrictModeViolationDialog.java b/services/java/com/android/server/am/StrictModeViolationDialog.java
index b6d0daa..5fee0d3 100644
--- a/services/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/java/com/android/server/am/StrictModeViolationDialog.java
@@ -16,14 +16,13 @@
package com.android.server.am;
-import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
-import android.util.Slog;
final class StrictModeViolationDialog extends BaseErrorDialog {
private final static String TAG = "StrictModeViolationDialog";
@@ -75,7 +74,7 @@
}
setTitle(res.getText(com.android.internal.R.string.aerr_title));
- getWindow().addFlags(FLAG_SYSTEM_ERROR);
+ getWindow().addFlags(PRIVATE_FLAG_SYSTEM_ERROR);
getWindow().setTitle("Strict Mode Violation: " + app.info.processName);
// After the timeout, pretend the user clicked the quit button
diff --git a/services/java/com/android/server/content/ContentService.java b/services/java/com/android/server/content/ContentService.java
index 7c82821..885ec9f 100644
--- a/services/java/com/android/server/content/ContentService.java
+++ b/services/java/com/android/server/content/ContentService.java
@@ -141,7 +141,7 @@
// The content service only throws security exceptions, so let's
// log all others.
if (!(e instanceof SecurityException)) {
- Log.e(TAG, "Content Service Crash", e);
+ Slog.wtf(TAG, "Content Service Crash", e);
}
throw e;
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 6cf3223..f093f2b 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1501,7 +1501,7 @@
return super.onTransact(code, data, reply, flags);
} catch (RuntimeException e) {
if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
- Slog.e(TAG, "Package Manager Crash", e);
+ Slog.wtf(TAG, "Package Manager Crash", e);
}
throw e;
}
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index fe09a33..2ccd21c 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -453,7 +453,8 @@
mDisplayPowerControllerCallbacks, mHandler);
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
- createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"));
+ createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
+ mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
diff --git a/services/java/com/android/server/power/WirelessChargerDetector.java b/services/java/com/android/server/power/WirelessChargerDetector.java
index 35920f7..38f5d77 100644
--- a/services/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/java/com/android/server/power/WirelessChargerDetector.java
@@ -21,8 +21,11 @@
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.Message;
import android.os.SystemClock;
import android.util.Slog;
+import android.util.TimeUtils;
import java.io.PrintWriter;
@@ -70,12 +73,12 @@
private static final String TAG = "WirelessChargerDetector";
private static final boolean DEBUG = false;
- // Number of nanoseconds per millisecond.
- private static final long NANOS_PER_MS = 1000000;
-
// The minimum amount of time to spend watching the sensor before making
// a determination of whether movement occurred.
- private static final long SETTLE_TIME_NANOS = 500 * NANOS_PER_MS;
+ private static final long SETTLE_TIME_MILLIS = 800;
+
+ // The sensor sampling interval.
+ private static final int SAMPLING_INTERVAL_MILLIS = 50;
// The minimum number of samples that must be collected.
private static final int MIN_SAMPLES = 3;
@@ -97,6 +100,7 @@
private final SensorManager mSensorManager;
private final SuspendBlocker mSuspendBlocker;
+ private final Handler mHandler;
// The gravity sensor, or null if none.
private Sensor mGravitySensor;
@@ -116,6 +120,9 @@
// The suspend blocker is held while this is the case.
private boolean mDetectionInProgress;
+ // The time when detection was last performed.
+ private long mDetectionStartTime;
+
// True if the rest position should be updated if at rest.
// Otherwise, the current rest position is simply checked and cleared if movement
// is detected but no new rest position is stored.
@@ -127,18 +134,17 @@
// The number of samples collected that showed evidence of not being at rest.
private int mMovingSamples;
- // The time and value of the first sample that was collected.
- private long mFirstSampleTime;
+ // The value of the first sample that was collected.
private float mFirstSampleX, mFirstSampleY, mFirstSampleZ;
- // The time and value of the last sample that was collected (for debugging only).
- private long mLastSampleTime;
+ // The value of the last sample that was collected.
private float mLastSampleX, mLastSampleY, mLastSampleZ;
public WirelessChargerDetector(SensorManager sensorManager,
- SuspendBlocker suspendBlocker) {
+ SuspendBlocker suspendBlocker, Handler handler) {
mSensorManager = sensorManager;
mSuspendBlocker = suspendBlocker;
+ mHandler = handler;
mGravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
}
@@ -152,13 +158,13 @@
pw.println(" mAtRest=" + mAtRest);
pw.println(" mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ);
pw.println(" mDetectionInProgress=" + mDetectionInProgress);
+ pw.println(" mDetectionStartTime=" + (mDetectionStartTime == 0 ? "0 (never)"
+ : TimeUtils.formatUptime(mDetectionStartTime)));
pw.println(" mMustUpdateRestPosition=" + mMustUpdateRestPosition);
pw.println(" mTotalSamples=" + mTotalSamples);
pw.println(" mMovingSamples=" + mMovingSamples);
- pw.println(" mFirstSampleTime=" + mFirstSampleTime);
pw.println(" mFirstSampleX=" + mFirstSampleX
+ ", mFirstSampleY=" + mFirstSampleY + ", mFirstSampleZ=" + mFirstSampleZ);
- pw.println(" mLastSampleTime=" + mLastSampleTime);
pw.println(" mLastSampleX=" + mLastSampleX
+ ", mLastSampleY=" + mLastSampleY + ", mLastSampleZ=" + mLastSampleZ);
}
@@ -217,22 +223,56 @@
private void startDetectionLocked() {
if (!mDetectionInProgress && mGravitySensor != null) {
if (mSensorManager.registerListener(mListener, mGravitySensor,
- SensorManager.SENSOR_DELAY_UI)) {
+ SAMPLING_INTERVAL_MILLIS * 1000)) {
mSuspendBlocker.acquire();
mDetectionInProgress = true;
+ mDetectionStartTime = SystemClock.uptimeMillis();
mTotalSamples = 0;
mMovingSamples = 0;
+
+ Message msg = Message.obtain(mHandler, mSensorTimeout);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, SETTLE_TIME_MILLIS);
}
}
}
- private void processSample(long timeNanos, float x, float y, float z) {
- synchronized (mLock) {
- if (!mDetectionInProgress) {
- return;
+ private void finishDetectionLocked() {
+ if (mDetectionInProgress) {
+ mSensorManager.unregisterListener(mListener);
+ mHandler.removeCallbacks(mSensorTimeout);
+
+ if (mMustUpdateRestPosition) {
+ clearAtRestLocked();
+ if (mTotalSamples < MIN_SAMPLES) {
+ Slog.w(TAG, "Wireless charger detector is broken. Only received "
+ + mTotalSamples + " samples from the gravity sensor but we "
+ + "need at least " + MIN_SAMPLES + " and we expect to see "
+ + "about " + SETTLE_TIME_MILLIS / SAMPLING_INTERVAL_MILLIS
+ + " on average.");
+ } else if (mMovingSamples == 0) {
+ mAtRest = true;
+ mRestX = mLastSampleX;
+ mRestY = mLastSampleY;
+ mRestZ = mLastSampleZ;
+ }
+ mMustUpdateRestPosition = false;
}
- mLastSampleTime = timeNanos;
+ if (DEBUG) {
+ Slog.d(TAG, "New state: mAtRest=" + mAtRest
+ + ", mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
+ + ", mTotalSamples=" + mTotalSamples
+ + ", mMovingSamples=" + mMovingSamples);
+ }
+
+ mDetectionInProgress = false;
+ mSuspendBlocker.release();
+ }
+ }
+
+ private void processSampleLocked(float x, float y, float z) {
+ if (mDetectionInProgress) {
mLastSampleX = x;
mLastSampleY = y;
mLastSampleZ = z;
@@ -240,7 +280,6 @@
mTotalSamples += 1;
if (mTotalSamples == 1) {
// Save information about the first sample collected.
- mFirstSampleTime = timeNanos;
mFirstSampleX = x;
mFirstSampleY = y;
mFirstSampleZ = z;
@@ -260,32 +299,6 @@
}
clearAtRestLocked();
}
-
- // Save the result when done.
- if (timeNanos - mFirstSampleTime >= SETTLE_TIME_NANOS
- && mTotalSamples >= MIN_SAMPLES) {
- mSensorManager.unregisterListener(mListener);
- if (mMustUpdateRestPosition) {
- if (mMovingSamples == 0) {
- mAtRest = true;
- mRestX = x;
- mRestY = y;
- mRestZ = z;
- } else {
- clearAtRestLocked();
- }
- mMustUpdateRestPosition = false;
- }
- mDetectionInProgress = false;
- mSuspendBlocker.release();
-
- if (DEBUG) {
- Slog.d(TAG, "New state: mAtRest=" + mAtRest
- + ", mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
- + ", mTotalSamples=" + mTotalSamples
- + ", mMovingSamples=" + mMovingSamples);
- }
- }
}
}
@@ -323,14 +336,22 @@
private final SensorEventListener mListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
- // We use SystemClock.elapsedRealtimeNanos() instead of event.timestamp because
- // on some devices the sensor HAL may produce timestamps that are not monotonic.
- processSample(SystemClock.elapsedRealtimeNanos(),
- event.values[0], event.values[1], event.values[2]);
+ synchronized (mLock) {
+ processSampleLocked(event.values[0], event.values[1], event.values[2]);
+ }
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
+
+ private final Runnable mSensorTimeout = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ finishDetectionLocked();
+ }
+ }
+ };
}
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index bc70fe3..3b0ee24 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -134,6 +134,11 @@
}
if (service != null) {
service.onPrintJobQueued(printJob);
+ } else {
+ // The service for the job is no longer enabled, so just
+ // fail the job with the appropriate message.
+ mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
+ mContext.getString(R.string.reason_service_unavailable));
}
}
@@ -779,7 +784,7 @@
for (int i = 0; i < printJobCount; i++) {
PrintJobInfo printJob = printJobs.get(i);
mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
- mContext.getString(R.string.reason_unknown));
+ mContext.getString(R.string.reason_service_unavailable));
}
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 1d95c44..87cabc9 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -126,7 +126,7 @@
} catch (RuntimeException e) {
// Log all 'real' exceptions thrown to the caller
if (!(e instanceof SecurityException)) {
- Slog.e(WindowManagerService.TAG, "Window Session Crash", e);
+ Slog.wtf(WindowManagerService.TAG, "Window Session Crash", e);
}
throw e;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index e6b0531..713aeee 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -813,7 +813,7 @@
// The window manager only throws security exceptions, so let's
// log all others.
if (!(e instanceof SecurityException)) {
- Log.wtf(TAG, "Window Manager Crash", e);
+ Slog.wtf(TAG, "Window Manager Crash", e);
}
throw e;
}
@@ -2793,7 +2793,7 @@
if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
+ " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
- win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
+ win.mEnforceSizeCompat = (win.mAttrs.flags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
winAnimator.mAlpha = attrs.alpha;
@@ -3379,6 +3379,18 @@
Binder.restoreCallingIdentity(origId);
}
+ private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
+ final TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
+ }
+ Task task = new Task(atoken, stack, userId);
+ stack.addTask(task, true);
+ stack.getDisplayContent().moveStack(stack, true);
+ mTaskIdToTask.put(taskId, task);
+ return task;
+ }
+
@Override
public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId) {
@@ -3418,14 +3430,7 @@
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
- TaskStack stack = mStackIdToStack.get(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
- }
- task = new Task(atoken, stack, userId);
- stack.addTask(task, true);
- stack.getDisplayContent().moveStack(stack, true);
- mTaskIdToTask.put(taskId, task);
+ task = createTask(taskId, stackId, userId, atoken);
} else {
task.addAppToken(addPos, atoken);
}
@@ -3459,8 +3464,7 @@
atoken.groupId = groupId;
Task newTask = mTaskIdToTask.get(groupId);
if (newTask == null) {
- throw new IllegalStateException("setAppGroupId: groupId=" + groupId
- + " does not exist");
+ newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
}
newTask.mAppTokens.add(atoken);
}
@@ -4786,6 +4790,7 @@
synchronized(mWindowMap) {
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
+ // Normal behavior, addAppToken will be called next and task will be created.
return;
}
final TaskStack stack = task.mStack;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 64b5a09..d56e225 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -20,7 +20,7 @@
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -332,7 +332,7 @@
mContext = mService.mContext;
DeathRecipient deathRecipient = new DeathRecipient();
mSeq = seq;
- mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
+ mEnforceSizeCompat = (mAttrs.flags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);