Merge "Make RegisteredServicesCache multi-user aware." into jb-mr1-dev
diff --git a/api/17.txt b/api/17.txt
index f8ad4d9..bebd566 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -16620,6 +16620,8 @@
method public android.os.UserHandle getUserForSerialNumber(long);
method public java.lang.String getUserName();
method public boolean isUserAGoat();
+ method public boolean isUserRunning(android.os.UserHandle);
+ method public boolean isUserRunningOrStopping(android.os.UserHandle);
}
public abstract class Vibrator {
diff --git a/api/current.txt b/api/current.txt
index f8ad4d9..bebd566 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16620,6 +16620,8 @@
method public android.os.UserHandle getUserForSerialNumber(long);
method public java.lang.String getUserName();
method public boolean isUserAGoat();
+ method public boolean isUserRunning(android.os.UserHandle);
+ method public boolean isUserRunningOrStopping(android.os.UserHandle);
}
public abstract class Vibrator {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3df88bb..add7a23 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -415,6 +415,10 @@
ComponentName cn = mAm.startService(null, intent, intent.getType(), mUserId);
if (cn == null) {
System.err.println("Error: Not found; no service started.");
+ } else if (cn.getPackageName().equals("!")) {
+ System.err.println("Error: Requires permission " + cn.getClassName());
+ } else if (cn.getPackageName().equals("!!")) {
+ System.err.println("Error: " + cn.getClassName());
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 0eda6b4..594be68 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1981,7 +1981,7 @@
*/
public boolean isUserRunning(int userid) {
try {
- return ActivityManagerNative.getDefault().isUserRunning(userid);
+ return ActivityManagerNative.getDefault().isUserRunning(userid, false);
} catch (RemoteException e) {
return false;
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index bb62c9e..7492629 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1608,7 +1608,8 @@
case IS_USER_RUNNING_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int userid = data.readInt();
- boolean result = isUserRunning(userid);
+ boolean orStopping = data.readInt() != 0;
+ boolean result = isUserRunning(userid, orStopping);
reply.writeNoException();
reply.writeInt(result ? 1 : 0);
return true;
@@ -3865,11 +3866,12 @@
return userInfo;
}
- public boolean isUserRunning(int userid) throws RemoteException {
+ public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(userid);
+ data.writeInt(orStopping ? 1 : 0);
mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
reply.readException();
boolean result = reply.readInt() != 0;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c324da92..3e1e358 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1352,10 +1352,16 @@
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
- if (cn != null && cn.getPackageName().equals("!")) {
- throw new SecurityException(
- "Not allowed to start service " + service
- + " without permission " + cn.getClassName());
+ if (cn != null) {
+ if (cn.getPackageName().equals("!")) {
+ throw new SecurityException(
+ "Not allowed to start service " + service
+ + " without permission " + cn.getClassName());
+ } else if (cn.getPackageName().equals("!!")) {
+ throw new SecurityException(
+ "Unable to start service " + service
+ + ": " + cn.getClassName());
+ }
}
return cn;
} catch (RemoteException e) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index da844ef..97250e9 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -326,7 +326,7 @@
public boolean switchUser(int userid) throws RemoteException;
public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
public UserInfo getCurrentUser() throws RemoteException;
- public boolean isUserRunning(int userid) throws RemoteException;
+ public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
public int[] getRunningUserIds() throws RemoteException;
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 1e8671b..6624eb8 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -18,13 +18,18 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
+import android.media.IAudioService;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
import android.text.TextUtils;
import android.view.Surface;
@@ -192,7 +197,21 @@
* Returns the information about a particular camera.
* If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
*/
- public native static void getCameraInfo(int cameraId, CameraInfo cameraInfo);
+ public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) {
+ _getCameraInfo(cameraId, cameraInfo);
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ IAudioService audioService = IAudioService.Stub.asInterface(b);
+ try {
+ if (audioService.isCameraSoundForced()) {
+ // Only set this when sound is forced; otherwise let native code
+ // decide.
+ cameraInfo.canDisableShutterSound = false;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Audio service is unavailable for queries");
+ }
+ }
+ private native static void _getCameraInfo(int cameraId, CameraInfo cameraInfo);
/**
* Information about a camera
@@ -1185,7 +1204,20 @@
* @see CameraInfo#canDisableShutterSound
* @see ShutterCallback
*/
- public native final boolean enableShutterSound(boolean enabled);
+ public final boolean enableShutterSound(boolean enabled) {
+ if (!enabled) {
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ IAudioService audioService = IAudioService.Stub.asInterface(b);
+ try {
+ if (audioService.isCameraSoundForced()) return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Audio service is unavailable for queries");
+ }
+ }
+ return _enableShutterSound(enabled);
+ }
+
+ private native final boolean _enableShutterSound(boolean enabled);
/**
* Callback interface for zoom changes during a smooth zoom operation.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 83a0c78..2739cac 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -16,6 +16,8 @@
package android.os;
import com.android.internal.R;
+
+import android.app.ActivityManagerNative;
import android.content.Context;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
@@ -82,6 +84,39 @@
}
/**
+ * Return whether the given user is actively running. This means that
+ * the user is in the "started" state, not "stopped" -- it is currently
+ * allowed to run code through scheduled alarms, receiving broadcasts,
+ * etc. A started user may be either the current foreground user or a
+ * background user; the result here does not distinguish between the two.
+ * @param user The user to retrieve the running state for.
+ */
+ public boolean isUserRunning(UserHandle user) {
+ try {
+ return ActivityManagerNative.getDefault().isUserRunning(
+ user.getIdentifier(), false);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Return whether the given user is actively running <em>or</em> stopping.
+ * This is like {@link #isUserRunning(UserHandle)}, but will also return
+ * true if the user had been running but is in the process of being stopped
+ * (but is not yet fully stopped, and still running some code).
+ * @param user The user to retrieve the running state for.
+ */
+ public boolean isUserRunningOrStopping(UserHandle user) {
+ try {
+ return ActivityManagerNative.getDefault().isUserRunning(
+ user.getIdentifier(), true);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
* Returns the UserInfo object describing a specific user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param userHandle the user handle of the user whose information is being requested.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 91c6db5..3c4a8fe 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5321,6 +5321,7 @@
ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED,
WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+ WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
WIFI_NUM_OPEN_NETWORKS_KEPT,
EMERGENCY_TONE,
CALL_AUTO_RETRY,
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index cb78763a..f865455 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -120,7 +120,7 @@
private boolean mInteractive = false;
private boolean mLowProfile = true;
private boolean mFullscreen = false;
- private boolean mScreenBright = false;
+ private boolean mScreenBright = true;
private boolean mFinished;
private boolean mDebug = false;
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index a74e438..ee3f5d8 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -17,6 +17,7 @@
package android.view;
import android.content.Context;
+import android.content.res.Resources;
import android.os.SystemClock;
import android.util.FloatMath;
@@ -162,9 +163,11 @@
mContext = context;
mListener = listener;
mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
- mTouchMinMajor =
- (int) (context.getResources().getDisplayMetrics().density * TOUCH_MIN_MAJOR + 0.5f);
- mMinSpan = context.getResources().getDimensionPixelSize(
+
+ final Resources res = context.getResources();
+ mTouchMinMajor = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.config_minScalingTouchMajor);
+ mMinSpan = res.getDimensionPixelSize(
com.android.internal.R.dimen.config_minScalingSpan);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ae51c1d..0d76eac 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6858,12 +6858,12 @@
/**
* Performs the specified accessibility action on the view. For
* possible accessibility actions look at {@link AccessibilityNodeInfo}.
- * <p>
- * If an {@link AccessibilityDelegate} has been specified via calling
- * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
- * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
- * is responsible for handling this call.
- * </p>
+ * <p>
+ * If an {@link AccessibilityDelegate} has been specified via calling
+ * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
+ * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
+ * is responsible for handling this call.
+ * </p>
*
* @param action The action to perform.
* @param arguments Optional action arguments.
@@ -6886,12 +6886,14 @@
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK: {
if (isClickable()) {
- return performClick();
+ performClick();
+ return true;
}
} break;
case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
if (isLongClickable()) {
- return performLongClick();
+ performLongClick();
+ return true;
}
} break;
case AccessibilityNodeInfo.ACTION_FOCUS: {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 410a0ca..b75c1e6 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -33,6 +33,7 @@
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.ExtractEditText;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -132,6 +133,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Locale;
+import java.util.concurrent.locks.ReentrantLock;
/**
* Displays text to the user and optionally allows them to edit it. A TextView
@@ -378,6 +380,9 @@
private InputFilter[] mFilters = NO_FILTERS;
+ private volatile Locale mCurrentTextServicesLocaleCache;
+ private final ReentrantLock mCurrentTextServicesLocaleLock = new ReentrantLock();
+
// It is possible to have a selection even when mEditor is null (programmatically set, like when
// a link is pressed). These highlight-related fields do not go in mEditor.
int mHighlightColor = 0x6633B5E5;
@@ -451,6 +456,8 @@
final Resources res = getResources();
final CompatibilityInfo compat = res.getCompatibilityInfo();
+ updateTextServicesLocaleAsync();
+
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.density = res.getDisplayMetrics().density;
mTextPaint.setCompatibilityScaling(compat.applicationScale);
@@ -7675,13 +7682,43 @@
/**
* This is a temporary method. Future versions may support multi-locale text.
+ * Caveat: This method may not return the latest text services locale, but this should be
+ * acceptable and it's more important to make this method asynchronous.
*
* @return The locale that should be used for a word iterator and a spell checker
* in this TextView, based on the current spell checker settings,
* the current IME's locale, or the system default locale.
* @hide
*/
+ // TODO: Support multi-locale
+ // TODO: Update the text services locale immediately after the keyboard locale is switched
+ // by catching intent of keyboard switch event
public Locale getTextServicesLocale() {
+ if (mCurrentTextServicesLocaleCache == null) {
+ // If there is no cached text services locale, just return the default locale.
+ mCurrentTextServicesLocaleCache = Locale.getDefault();
+ }
+ // Start fetching the text services locale asynchronously.
+ updateTextServicesLocaleAsync();
+ return mCurrentTextServicesLocaleCache;
+ }
+
+ private void updateTextServicesLocaleAsync() {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ if (mCurrentTextServicesLocaleLock.tryLock()) {
+ try {
+ updateTextServicesLocaleLocked();
+ } finally {
+ mCurrentTextServicesLocaleLock.unlock();
+ }
+ }
+ }
+ });
+ }
+
+ private void updateTextServicesLocaleLocked() {
Locale locale = Locale.getDefault();
final TextServicesManager textServicesManager = (TextServicesManager)
mContext.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
@@ -7689,7 +7726,7 @@
if (subtype != null) {
locale = SpellCheckerSubtype.constructLocaleFromString(subtype.getLocale());
}
- return locale;
+ mCurrentTextServicesLocaleCache = locale;
}
void onLocaleChanged() {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 2811332..4bb6d06 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -476,6 +476,9 @@
if (isAction) maxActions--;
item.setIsActionButton(isAction);
+ } else {
+ // Neither requires nor requests an action button.
+ item.setIsActionButton(false);
}
}
return true;
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 99d49ec..67d831c 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -854,7 +854,7 @@
{ "getNumberOfCameras",
"()I",
(void *)android_hardware_Camera_getNumberOfCameras },
- { "getCameraInfo",
+ { "_getCameraInfo",
"(ILandroid/hardware/Camera$CameraInfo;)V",
(void*)android_hardware_Camera_getCameraInfo },
{ "native_setup",
@@ -917,7 +917,7 @@
{ "setDisplayOrientation",
"(I)V",
(void *)android_hardware_Camera_setDisplayOrientation },
- { "enableShutterSound",
+ { "_enableShutterSound",
"(Z)Z",
(void *)android_hardware_Camera_enableShutterSound },
{ "_startFaceDetection",
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a00f071..4698002 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -941,6 +941,10 @@
reported by the hardware. -->
<dimen name="config_minScalingSpan">27mm</dimen>
+ <!-- Minimum accepted value for touchMajor while scaling. This may be tuned
+ per-device in overlays. -->
+ <dimen name="config_minScalingTouchMajor">48dp</dimen>
+
<!-- Safe headphone volume index. When music stream volume is below this index
the SPL on headphone output is compliant to EN 60950 requirements for portable music
players. -->
@@ -984,4 +988,9 @@
<!-- Whether camera shutter sound is forced or not (country specific). -->
<bool name="config_camera_sound_forced">false</bool>
+ <!-- Set to true if we need to not prefer an APN.
+ This is being added to enable a simple scenario of pre-paid
+ provisioning on some carriers, working around a bug (7305641)
+ where if the preferred is used we don't try the others. -->
+ <bool name="config_dontPreferApn">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e615fd4..c48de1f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -276,6 +276,7 @@
<java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
<java-symbol type="bool" name="config_safe_media_volume_enabled" />
<java-symbol type="bool" name="config_camera_sound_forced" />
+ <java-symbol type="bool" name="config_dontPreferApn" />
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_longPressOnPowerBehavior" />
@@ -1150,6 +1151,7 @@
<java-symbol type="string" name="bluetooth_a2dp_audio_route_name" />
<java-symbol type="dimen" name="config_minScalingSpan" />
+ <java-symbol type="dimen" name="config_minScalingTouchMajor" />
<!-- From android.policy -->
<java-symbol type="anim" name="app_starting_exit" />
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
index a6cf355..3d5905d 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
@@ -38,7 +38,7 @@
public class MediaFrameworkPerfTestRunner extends InstrumentationTestRunner {
public static boolean mGetNativeHeapDump = false;
-
+ public static boolean mGetProcmem = false;
@Override
public TestSuite getAllTests() {
@@ -61,6 +61,12 @@
if (get_heap_dump != null) {
mGetNativeHeapDump = true;
}
+
+ String get_procmem = (String) icicle.get("get_procmem");
+ if (get_procmem != null) {
+ mGetProcmem = true;
+ }
+
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index ccb0638..9b1098e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2008 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
@@ -53,7 +53,7 @@
import com.android.mediaframeworktest.MediaProfileReader;
/**
- * Junit / Instrumentation - performance measurement for media player and
+ * Junit / Instrumentation - performance measurement for media player and
* recorder
*
* FIXME:
@@ -100,6 +100,7 @@
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
}
+ @Override
protected void setUp() throws Exception {
super.setUp();
//Insert a 2 second before launching the test activity. This is
@@ -109,19 +110,26 @@
if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
MediaTestUtil.getNativeHeapDump(this.getName() + "_before");
- mProcMemWriter = new BufferedWriter(new FileWriter
- (new File(MEDIA_PROCMEM_OUTPUT), true));
- mProcMemWriter.write(this.getName() + "\n");
- mMemWriter = new BufferedWriter(new FileWriter
- (new File(MEDIA_MEMORY_OUTPUT), true));
+ if (MediaFrameworkPerfTestRunner.mGetProcmem) {
+ mProcMemWriter = new BufferedWriter(new FileWriter
+ (new File(MEDIA_PROCMEM_OUTPUT), true));
+ mProcMemWriter.write(this.getName() + "\n");
+ mMemWriter = new BufferedWriter(new FileWriter
+ (new File(MEDIA_MEMORY_OUTPUT), true));
+ }
}
+ @Override
protected void tearDown() throws Exception {
if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump)
MediaTestUtil.getNativeHeapDump(this.getName() + "_after");
- mProcMemWriter.close();
- mMemWriter.close();
+
+ if (MediaFrameworkPerfTestRunner.mGetProcmem) {
+ mMemWriter.write("\n");
+ mProcMemWriter.close();
+ mMemWriter.close();
+ }
super.tearDown();
}
@@ -157,6 +165,7 @@
}
private final class RawPreviewCallback implements PreviewCallback {
+ @Override
public void onPreviewFrame(byte[] rawData, Camera camera) {
mPreviewDone.open();
}
@@ -285,19 +294,21 @@
}
}
- public void writeProcmemInfo() throws Exception{
- String cmd = "procmem " + getMediaserverPid();
- Process p = Runtime.getRuntime().exec(cmd);
+ public void writeProcmemInfo() throws Exception {
+ if (MediaFrameworkPerfTestRunner.mGetProcmem) {
+ String cmd = "procmem " + getMediaserverPid();
+ Process p = Runtime.getRuntime().exec(cmd);
- InputStream inStream = p.getInputStream();
- InputStreamReader inReader = new InputStreamReader(inStream);
- BufferedReader inBuffer = new BufferedReader(inReader);
- String s;
- while ((s = inBuffer.readLine()) != null) {
- mProcMemWriter.write(s);
- mProcMemWriter.write("\n");
+ InputStream inStream = p.getInputStream();
+ InputStreamReader inReader = new InputStreamReader(inStream);
+ BufferedReader inBuffer = new BufferedReader(inReader);
+ String s;
+ while ((s = inBuffer.readLine()) != null) {
+ mProcMemWriter.write(s);
+ mProcMemWriter.write("\n");
+ }
+ mProcMemWriter.write("\n\n");
}
- mProcMemWriter.write("\n\n");
}
public String captureMediaserverInfo() {
@@ -368,13 +379,11 @@
boolean memoryResult = false;
mStartPid = getMediaserverPid();
- mMemWriter.write("H263 Video Playback Only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
getMemoryWriteToLog(i);
writeProcmemInfo();
}
- mMemWriter.write("\n");
memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
assertTrue("H263 playback memory test", memoryResult);
}
@@ -385,13 +394,11 @@
boolean memoryResult = false;
mStartPid = getMediaserverPid();
- mMemWriter.write("H264 Video Playback only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
getMemoryWriteToLog(i);
writeProcmemInfo();
}
- mMemWriter.write("\n");
memoryResult = validateMemoryResult(mStartPid, mStartMemory, DECODER_LIMIT);
assertTrue("H264 playback memory test", memoryResult);
}
@@ -402,7 +409,6 @@
boolean memoryResult = false;
mStartPid = getMediaserverPid();
- mMemWriter.write("H263 video record only\n");
int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
assertTrue("H263 video recording frame rate", frameRate != -1);
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
@@ -411,7 +417,6 @@
getMemoryWriteToLog(i);
writeProcmemInfo();
}
- mMemWriter.write("\n");
memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("H263 record only memory test", memoryResult);
}
@@ -422,7 +427,6 @@
boolean memoryResult = false;
mStartPid = getMediaserverPid();
- mMemWriter.write("MPEG4 video record only\n");
int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.MPEG_4_SP);
assertTrue("MPEG4 video recording frame rate", frameRate != -1);
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
@@ -431,7 +435,6 @@
getMemoryWriteToLog(i);
writeProcmemInfo();
}
- mMemWriter.write("\n");
memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("mpeg4 record only memory test", memoryResult);
}
@@ -445,14 +448,12 @@
mStartPid = getMediaserverPid();
int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
assertTrue("H263 video recording frame rate", frameRate != -1);
- mMemWriter.write("Audio and h263 video record\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.H263,
MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false));
getMemoryWriteToLog(i);
writeProcmemInfo();
}
- mMemWriter.write("\n");
memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("H263 audio video record memory test", memoryResult);
}
@@ -463,13 +464,11 @@
boolean memoryResult = false;
mStartPid = getMediaserverPid();
- mMemWriter.write("Audio record only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
stressAudioRecord(MediaNames.RECORDER_OUTPUT);
getMemoryWriteToLog(i);
writeProcmemInfo();
}
- mMemWriter.write("\n");
memoryResult = validateMemoryResult(mStartPid, mStartMemory, ENCODER_LIMIT);
assertTrue("audio record only memory test", memoryResult);
}
@@ -480,13 +479,11 @@
boolean memoryResult = false;
mStartPid = getMediaserverPid();
- mMemWriter.write("Camera Preview Only\n");
for (int i = 0; i < NUM_STRESS_LOOP; i++) {
stressCameraPreview();
getMemoryWriteToLog(i);
writeProcmemInfo();
}
- mMemWriter.write("\n");
memoryResult = validateMemoryResult(mStartPid, mStartMemory, CAMERA_LIMIT);
assertTrue("camera preview memory test", memoryResult);
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 0a0474c..0b85e70 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -26,6 +26,7 @@
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.FileUtils;
+import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.provider.Settings;
@@ -61,12 +62,6 @@
private static final boolean DEBUG = false;
private static final boolean DEBUG_BACKUP = DEBUG || false;
- /* Don't restore wifi config until we have new logic for parsing the
- * saved wifi config and configuring the new APs without having to
- * disable and re-enable wifi
- */
- private static final boolean NAIVE_WIFI_RESTORE = false;
-
private static final String KEY_SYSTEM = "system";
private static final String KEY_SECURE = "secure";
private static final String KEY_GLOBAL = "global";
@@ -127,10 +122,16 @@
// stored in the full-backup tarfile as well, so should not be changed.
private static final String STAGE_FILE = "flattened-data";
+ // Delay in milliseconds between the restore operation and when we will bounce
+ // wifi in order to rewrite the supplicant config etc.
+ private static final long WIFI_BOUNCE_DELAY_MILLIS = 60 * 1000; // one minute
+
private SettingsHelper mSettingsHelper;
private WifiManager mWfm;
private static String mWifiConfigFile;
+ WifiRestoreRunnable mWifiRestore = null;
+
// Class for capturing a network definition from the wifi supplicant config file
static class Network {
String ssid = ""; // equals() and hashCode() need these to be non-null
@@ -297,6 +298,66 @@
writeNewChecksums(stateChecksums, newState);
}
+ class WifiRestoreRunnable implements Runnable {
+ private byte[] restoredSupplicantData;
+ private byte[] restoredWifiConfigFile;
+
+ void incorporateWifiSupplicant(BackupDataInput data) {
+ restoredSupplicantData = new byte[data.getDataSize()];
+ if (restoredSupplicantData.length <= 0) return;
+ try {
+ data.readEntityData(restoredSupplicantData, 0, data.getDataSize());
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to read supplicant data");
+ restoredSupplicantData = null;
+ }
+ }
+
+ void incorporateWifiConfigFile(BackupDataInput data) {
+ restoredWifiConfigFile = new byte[data.getDataSize()];
+ if (restoredWifiConfigFile.length <= 0) return;
+ try {
+ data.readEntityData(restoredWifiConfigFile, 0, data.getDataSize());
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to read config file");
+ restoredWifiConfigFile = null;
+ }
+ }
+
+ @Override
+ public void run() {
+ if (restoredSupplicantData != null || restoredWifiConfigFile != null) {
+ if (DEBUG_BACKUP) {
+ Log.v(TAG, "Starting deferred restore of wifi data");
+ }
+ final int retainedWifiState = enableWifi(false);
+ if (restoredSupplicantData != null) {
+ restoreWifiSupplicant(FILE_WIFI_SUPPLICANT,
+ restoredSupplicantData, restoredSupplicantData.length);
+ FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR |
+ FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ Process.myUid(), Process.WIFI_UID);
+ }
+ if (restoredWifiConfigFile != null) {
+ restoreFileData(mWifiConfigFile,
+ restoredWifiConfigFile, restoredWifiConfigFile.length);
+ }
+ // restore the previous WIFI state.
+ enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
+ retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
+ }
+ }
+ }
+
+ // Instantiate the wifi-config restore runnable, scheduling it for execution
+ // a minute hence
+ void initWifiRestoreIfNecessary() {
+ if (mWifiRestore == null) {
+ mWifiRestore = new WifiRestoreRunnable();
+ }
+ }
+
@Override
public void onRestore(BackupDataInput data, int appVersionCode,
ParcelFileDescriptor newState) throws IOException {
@@ -315,26 +376,26 @@
restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal);
} else if (KEY_GLOBAL.equals(key)) {
restoreSettings(data, Settings.Global.CONTENT_URI, null);
- } else if (NAIVE_WIFI_RESTORE && KEY_WIFI_SUPPLICANT.equals(key)) {
- int retainedWifiState = enableWifi(false);
- restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, data);
- FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
- FileUtils.S_IRUSR | FileUtils.S_IWUSR |
- FileUtils.S_IRGRP | FileUtils.S_IWGRP,
- Process.myUid(), Process.WIFI_UID);
- // retain the previous WIFI state.
- enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
- retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
+ } else if (KEY_WIFI_SUPPLICANT.equals(key)) {
+ initWifiRestoreIfNecessary();
+ mWifiRestore.incorporateWifiSupplicant(data);
} else if (KEY_LOCALE.equals(key)) {
byte[] localeData = new byte[size];
data.readEntityData(localeData, 0, size);
mSettingsHelper.setLocaleData(localeData, size);
- } else if (NAIVE_WIFI_RESTORE && KEY_WIFI_CONFIG.equals(key)) {
- restoreFileData(mWifiConfigFile, data);
+ } else if (KEY_WIFI_CONFIG.equals(key)) {
+ initWifiRestoreIfNecessary();
+ mWifiRestore.incorporateWifiConfigFile(data);
} else {
data.skipEntityData();
}
}
+
+ // If we have wifi data to restore, post a runnable to perform the
+ // bounce-and-update operation a little ways in the future.
+ if (mWifiRestore != null) {
+ new Handler(getMainLooper()).postDelayed(mWifiRestore, WIFI_BOUNCE_DELAY_MILLIS);
+ }
}
@Override
@@ -619,7 +680,7 @@
getContentResolver().insert(destination, contentValues);
}
- if (DEBUG || true) {
+ if (DEBUG) {
Log.d(TAG, "Restored setting: " + destination + " : "+ key + "=" + value);
}
}
@@ -731,17 +792,6 @@
}
- private void restoreFileData(String filename, BackupDataInput data) {
- byte[] bytes = new byte[data.getDataSize()];
- if (bytes.length <= 0) return;
- try {
- data.readEntityData(bytes, 0, data.getDataSize());
- restoreFileData(filename, bytes, bytes.length);
- } catch (IOException e) {
- Log.w(TAG, "Unable to read file data for " + filename);
- }
- }
-
private void restoreFileData(String filename, byte[] bytes, int size) {
try {
File file = new File(filename);
@@ -794,17 +844,6 @@
}
}
- private void restoreWifiSupplicant(String filename, BackupDataInput data) {
- byte[] bytes = new byte[data.getDataSize()];
- if (bytes.length <= 0) return;
- try {
- data.readEntityData(bytes, 0, data.getDataSize());
- restoreWifiSupplicant(filename, bytes, bytes.length);
- } catch (IOException e) {
- Log.w(TAG, "Unable to read supplicant data");
- }
- }
-
private void restoreWifiSupplicant(String filename, byte[] bytes, int size) {
try {
WifiNetworkSettings supplicantImage = new WifiNetworkSettings();
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 64b660f..f0e5a87 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -108,6 +108,7 @@
</activity>
<activity android:name=".recent.RecentsActivity"
+ android:label="@string/accessibility_desc_recent_apps"
android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7ac27fe..e0b0227 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -377,6 +377,8 @@
<string name="accessibility_desc_notification_shade">Notification shade.</string>
<!-- Content description for the quick settings panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_quick_settings">Quick settings.</string>
+ <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_desc_recent_apps">Recent apps.</string>
<!-- Content description of the user tile in quick settings (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_user">User <xliff:g id="user" example="John Doe">%s</xliff:g>.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index e8772df..0937c46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -102,7 +102,7 @@
private int mBrightnessDialogShortTimeout;
private int mBrightnessDialogLongTimeout;
- private AsyncTask<Void, Void, Pair<String, BitmapDrawable>> mUserInfoTask;
+ private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
private LevelListDrawable mBatteryLevels;
private LevelListDrawable mChargingBatteryLevels;
@@ -203,35 +203,43 @@
final int userId = userInfo.id;
final Context context = currentUserContext;
- mUserInfoTask = new AsyncTask<Void, Void, Pair<String, BitmapDrawable>>() {
+ mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
@Override
- protected Pair<String, BitmapDrawable> doInBackground(Void... params) {
- Cursor cursor = context.getContentResolver().query(
+ protected Pair<String, Drawable> doInBackground(Void... params) {
+ final Cursor cursor = context.getContentResolver().query(
Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME},
null, null, null);
+ final UserManager um =
+ (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (cursor == null) {
- // Info not available. Should become available later.
- return new Pair<String, BitmapDrawable>(null, null);
+ // Fall back to the UserManager nickname if we can't read the name from the local
+ // profile below.
+ String nickName = um.getUserName();
+ String name = nickName;
+ Drawable avatar = null;
+ Bitmap rawAvatar = um.getUserIcon(userId);
+ if (rawAvatar != null) {
+ avatar = new BitmapDrawable(mContext.getResources(), rawAvatar);
+ } else {
+ avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user);
}
- String name = null;
- try {
- if (cursor.moveToFirst()) {
- name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
+ // Try and read the display name from the local profile
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
+ }
+ } finally {
+ cursor.close();
}
- } finally {
- cursor.close();
}
- final UserManager userManager =
- (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- final BitmapDrawable icon = new BitmapDrawable(mContext.getResources(),
- userManager.getUserIcon(userId));
- return new Pair<String, BitmapDrawable>(name, icon);
+
+ return new Pair<String, Drawable>(name, avatar);
}
@Override
- protected void onPostExecute(Pair<String, BitmapDrawable> result) {
+ protected void onPostExecute(Pair<String, Drawable> result) {
super.onPostExecute(result);
mModel.setUserTileInfo(result.first, result.second);
mUserInfoTask = null;
@@ -305,9 +313,7 @@
ImageView iv = (ImageView) view.findViewById(R.id.user_imageview);
TextView tv = (TextView) view.findViewById(R.id.user_textview);
tv.setText(state.label);
- if (us.avatar != null) {
- iv.setImageDrawable(us.avatar);
- }
+ iv.setImageDrawable(us.avatar);
view.setContentDescription(mContext.getString(
R.string.accessibility_quick_settings_user, state.label));
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index 6ea3513..840edaf 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -33,6 +33,8 @@
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.UserManager;
import android.util.AttributeSet;
import android.util.Log;
@@ -43,12 +45,14 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.View.BaseSavedState;
import android.view.animation.AnimationUtils;
import android.widget.RemoteViews.OnClickHandler;
import android.widget.ViewFlipper;
import com.android.internal.R;
import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.internal.policy.impl.keyguard.KeyguardTransportControlView.SavedState;
import com.android.internal.widget.LockPatternUtils;
import java.io.File;
@@ -64,6 +68,10 @@
static final int APPWIDGET_HOST_ID = 0x4B455947;
private static final String KEYGUARD_WIDGET_PREFS = "keyguard_widget_prefs";
+ private static final int TRANSPORT_GONE = 0;
+ private static final int TRANSPORT_INVISIBLE = 1;
+ private static final int TRANSPORT_VISIBLE = 2;
+
private AppWidgetHost mAppWidgetHost;
private KeyguardWidgetRegion mAppWidgetRegion;
private KeyguardWidgetPager mAppWidgetContainer;
@@ -83,10 +91,12 @@
private KeyguardSecurityModel mSecurityModel;
private Rect mTempRect = new Rect();
+ private int mTransportState = TRANSPORT_GONE;
/*package*/ interface TransportCallback {
- void hide();
- void show();
+ void onListenerDetached();
+ void onListenerAttached();
+ void onPlayStateChanged();
}
/*package*/ interface UserSwitcherCallback {
@@ -185,7 +195,7 @@
mAppWidgetHost.startListening();
maybePopulateWidgets();
disableStatusViewInteraction();
- showAppropriateWidgetPage();
+ post(mSwitchPageRunnable);
}
private void disableStatusViewInteraction() {
@@ -712,7 +722,7 @@
private void addDefaultWidgets() {
LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(R.layout.keyguard_status_view, mAppWidgetContainer, true);
- inflater.inflate(R.layout.keyguard_transport_control_view, mAppWidgetContainer, true);
+ inflater.inflate(R.layout.keyguard_transport_control_view, this, true);
inflateAndAddUserSelectorWidgetIfNecessary();
initializeTransportControl();
@@ -721,16 +731,16 @@
private void initializeTransportControl() {
mTransportControl =
(KeyguardTransportControlView) findViewById(R.id.keyguard_transport_control);
+ mTransportControl.setVisibility(View.GONE);
// This code manages showing/hiding the transport control. We keep it around and only
// add it to the hierarchy if it needs to be present.
if (mTransportControl != null) {
mTransportControl.setKeyguardCallback(new TransportCallback() {
- boolean mSticky = false;
@Override
- public void hide() {
+ public void onListenerDetached() {
int page = getWidgetPosition(R.id.keyguard_transport_control);
- if (page != -1 && !mSticky) {
+ if (page != -1) {
if (page == mAppWidgetContainer.getCurrentPage()) {
// Switch back to clock view if music was showing.
mAppWidgetContainer
@@ -741,20 +751,23 @@
// from AudioManager
KeyguardHostView.this.addView(mTransportControl);
mTransportControl.setVisibility(View.GONE);
+ mTransportState = TRANSPORT_GONE;
}
}
@Override
- public void show() {
+ public void onListenerAttached() {
if (getWidgetPosition(R.id.keyguard_transport_control) == -1) {
KeyguardHostView.this.removeView(mTransportControl);
- mAppWidgetContainer.addView(mTransportControl,
- getWidgetPosition(R.id.keyguard_status_view) + 1);
+ mAppWidgetContainer.addView(mTransportControl, 0);
mTransportControl.setVisibility(View.VISIBLE);
- // Once shown, leave it showing
- mSticky = true;
}
}
+
+ @Override
+ public void onPlayStateChanged() {
+ mTransportControl.post(mSwitchPageRunnable);
+ }
});
}
}
@@ -796,12 +809,87 @@
}
}
- private void showAppropriateWidgetPage() {
- int page = mAppWidgetContainer.indexOfChild(findViewById(R.id.keyguard_status_view));
- if (mAppWidgetContainer.indexOfChild(mTransportControl) != -1) {
- page = mAppWidgetContainer.indexOfChild(mTransportControl);
+ Runnable mSwitchPageRunnable = new Runnable() {
+ @Override
+ public void run() {
+ showAppropriateWidgetPage();
}
- mAppWidgetContainer.setCurrentPage(page);
+ };
+
+ static class SavedState extends BaseSavedState {
+ int transportState;
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ this.transportState = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeInt(this.transportState);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR
+ = new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+ SavedState ss = new SavedState(superState);
+ ss.transportState = mTransportState;
+ return ss;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ if (!(state instanceof SavedState)) {
+ super.onRestoreInstanceState(state);
+ return;
+ }
+ SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ mTransportState = ss.transportState;
+ post(mSwitchPageRunnable);
+ }
+
+ private void showAppropriateWidgetPage() {
+
+ // The following sets the priority for showing widgets. Transport should be shown if
+ // music is playing, followed by the multi-user widget if enabled, followed by the
+ // status widget.
+ final int pageToShow;
+ if (mTransportControl.isMusicPlaying() || mTransportState == TRANSPORT_VISIBLE) {
+ mTransportState = TRANSPORT_VISIBLE;
+ pageToShow = mAppWidgetContainer.indexOfChild(mTransportControl);
+ } else {
+ UserManager mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ final View multiUserView = findViewById(R.id.keyguard_multi_user_selector);
+ final int multiUserPosition = mAppWidgetContainer.indexOfChild(multiUserView);
+ if (multiUserPosition != -1 && mUm.getUsers(true).size() > 1) {
+ pageToShow = multiUserPosition;
+ } else {
+ final View statusView = findViewById(R.id.keyguard_status_view);
+ pageToShow = mAppWidgetContainer.indexOfChild(statusView);
+ }
+ if (mTransportState == TRANSPORT_VISIBLE) {
+ mTransportState = TRANSPORT_INVISIBLE;
+ }
+ }
+ mAppWidgetContainer.setCurrentPage(pageToShow);
}
private void inflateAndAddUserSelectorWidgetIfNecessary() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
index e3b7b01..b6b731e 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -28,6 +28,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.MediaStore;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -203,11 +204,18 @@
} else if (disabledBySimState) {
Log.v(TAG, "Camera disabled by Sim State");
}
+ boolean currentUserSetup = 0 != Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE,
+ 0 /*default */,
+ currentUserHandle);
boolean searchActionAvailable =
((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
.getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
- mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent;
- mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
+ mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
+ || !currentUserSetup;
+ mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
+ || !currentUserSetup;
updateResources();
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
index e2f3059..7e71f94 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
@@ -42,7 +42,6 @@
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
@@ -59,7 +58,7 @@
private static final int MSG_SET_GENERATION_ID = 104;
private static final int MAXDIM = 512;
private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
- protected static final boolean DEBUG = false;
+ protected static final boolean DEBUG = true;
protected static final String TAG = "TransportControlView";
private ImageView mAlbumArt;
@@ -75,6 +74,7 @@
private int mCurrentPlayState;
private AudioManager mAudioManager;
private IRemoteControlDisplayWeak mIRCD;
+ private boolean mMusicClientPresent = true;
/**
* The metadata which should be populated into the view once we've been attached
@@ -112,7 +112,9 @@
case MSG_SET_GENERATION_ID:
if (msg.arg2 != 0) {
// This means nobody is currently registered. Hide the view.
- hide();
+ onListenerDetached();
+ } else {
+ onListenerAttached();
}
if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
mClientGeneration = msg.arg1;
@@ -193,28 +195,26 @@
mIRCD = new IRemoteControlDisplayWeak(mHandler);
}
- protected void hide() {
- if (DEBUG) Log.v(TAG, "Transport was told to hide");
+ protected void onListenerDetached() {
+ mMusicClientPresent = false;
+ if (DEBUG) Log.v(TAG, "onListenerDetached()");
if (mTransportCallback != null) {
- mTransportCallback.hide();
+ mTransportCallback.onListenerDetached();
} else {
- Log.w(TAG, "Hide music, but callback wasn't set");
+ Log.w(TAG, "onListenerDetached: no callback");
}
}
- private void show() {
- if (DEBUG) Log.v(TAG, "Transport was told to show");
+ private void onListenerAttached() {
+ mMusicClientPresent = true;
+ if (DEBUG) Log.v(TAG, "onListenerAttached()");
if (mTransportCallback != null) {
- mTransportCallback.show();
+ mTransportCallback.onListenerAttached();
} else {
- Log.w(TAG, "Show music, but callback wasn't set");
+ Log.w(TAG, "onListenerAttached(): no callback");
}
}
- private void userActivity() {
- // TODO Auto-generated method stub
- }
-
private void updateTransportControls(int transportControlFlags) {
mTransportControlFlags = transportControlFlags;
}
@@ -341,6 +341,11 @@
updatePlayPauseState(mCurrentPlayState);
}
+ public boolean isMusicPlaying() {
+ return mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING
+ || mCurrentPlayState == RemoteControlClient.PLAYSTATE_BUFFERING;
+ }
+
private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
if ((flags & flag) != 0) {
view.setVisibility(View.VISIBLE);
@@ -357,7 +362,6 @@
}
final int imageResId;
final int imageDescId;
- boolean showIfHidden = false;
switch (state) {
case RemoteControlClient.PLAYSTATE_ERROR:
imageResId = com.android.internal.R.drawable.stat_sys_warning;
@@ -369,32 +373,27 @@
case RemoteControlClient.PLAYSTATE_PLAYING:
imageResId = com.android.internal.R.drawable.ic_media_pause;
imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description;
- showIfHidden = true;
break;
case RemoteControlClient.PLAYSTATE_BUFFERING:
imageResId = com.android.internal.R.drawable.ic_media_stop;
imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
- showIfHidden = true;
break;
case RemoteControlClient.PLAYSTATE_PAUSED:
default:
imageResId = com.android.internal.R.drawable.ic_media_play;
imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
- showIfHidden = false;
break;
}
mBtnPlay.setImageResource(imageResId);
mBtnPlay.setContentDescription(getResources().getString(imageDescId));
- if (showIfHidden) {
- show();
- }
mCurrentPlayState = state;
+ mTransportCallback.onPlayStateChanged();
}
static class SavedState extends BaseSavedState {
- boolean wasShowing;
+ boolean clientPresent;
SavedState(Parcelable superState) {
super(superState);
@@ -402,13 +401,13 @@
private SavedState(Parcel in) {
super(in);
- this.wasShowing = in.readInt() != 0;
+ this.clientPresent = in.readInt() != 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
- out.writeInt(this.wasShowing ? 1 : 0);
+ out.writeInt(this.clientPresent ? 1 : 0);
}
public static final Parcelable.Creator<SavedState> CREATOR
@@ -425,24 +424,23 @@
@Override
public Parcelable onSaveInstanceState() {
- if (DEBUG) Log.v(TAG, "onSaveInstanceState()");
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
- ss.wasShowing = getVisibility() == View.VISIBLE;
+ ss.clientPresent = mMusicClientPresent;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
- if (DEBUG) Log.v(TAG, "onRestoreInstanceState()");
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
- if (ss.wasShowing) {
- show();
+ if (ss.clientPresent) {
+ if (DEBUG) Log.v(TAG, "Reattaching client because it was attached");
+ onListenerAttached();
}
}
@@ -458,7 +456,6 @@
}
if (keyCode != -1) {
sendMediaButtonClick(keyCode);
- userActivity();
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index 33ff71e..3ffd43f 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -48,7 +48,7 @@
* reported to this class by the current {@link KeyguardViewBase}.
*/
public class KeyguardViewManager {
- private final static boolean DEBUG = false;
+ private final static boolean DEBUG = true;
private static String TAG = "KeyguardViewManager";
public static boolean USE_UPPER_CASE = true;
@@ -201,9 +201,6 @@
if (v != null) {
mKeyguardHost.removeView(v);
}
- // TODO: Remove once b/7094175 is fixed
- Slog.d(TAG, "inflateKeyguardView: b/7094175 mContext.config="
- + mContext.getResources().getConfiguration());
final LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.keyguard_host_view, mKeyguardHost, true);
mKeyguardView = (KeyguardHostView) view.findViewById(R.id.keyguard_host_view);
@@ -359,6 +356,12 @@
if (mKeyguardHost != null) {
mKeyguardHost.setVisibility(View.GONE);
+
+ // We really only want to preserve keyguard state for configuration changes. Hence
+ // we should clear state of widgets (e.g. Music) when we hide keyguard so it can
+ // start with a fresh state when we return.
+ mStateContainer.clear();
+
// Don't do this right away, so we can let the view continue to animate
// as it goes away.
if (mKeyguardView != null) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index ca28e4c..c5016e6 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -308,6 +308,7 @@
addProviderLocked(fusedLocationProvider);
mProxyProviders.add(fusedLocationProvider);
mEnabledProviders.add(fusedLocationProvider.getName());
+ mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
} else {
Slog.e(TAG, "no fused location provider found",
new IllegalStateException("Location service needs a fused location provider"));
diff --git a/services/java/com/android/server/WiredAccessoryManager.java b/services/java/com/android/server/WiredAccessoryManager.java
index 63e8895..d5c9c8f 100644
--- a/services/java/com/android/server/WiredAccessoryManager.java
+++ b/services/java/com/android/server/WiredAccessoryManager.java
@@ -152,7 +152,7 @@
break;
}
- updateLocked(NAME_H2W, headset);
+ updateLocked(NAME_H2W, (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC)) | headset);
}
}
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 7e3fdbd..35999ea 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -248,8 +248,9 @@
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
- if (!bringUpServiceLocked(r, service.getFlags(), false)) {
- return new ComponentName("!", "Service process is bad");
+ String error = bringUpServiceLocked(r, service.getFlags(), false);
+ if (error != null) {
+ return new ComponentName("!!", error);
}
return r.name;
}
@@ -518,7 +519,7 @@
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
- if (!bringUpServiceLocked(s, service.getFlags(), false)) {
+ if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
return 0;
}
}
@@ -964,19 +965,19 @@
return true;
}
- private final boolean bringUpServiceLocked(ServiceRecord r,
+ private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, false);
- return true;
+ return null;
}
if (!whileRestarting && r.restartDelay > 0) {
// If waiting for a restart, then do nothing.
- return true;
+ return null;
}
if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
@@ -988,12 +989,13 @@
// Make sure that the user who owns this service is started. If not,
// we don't want to allow it to run.
if (mAm.mStartedUsers.get(r.userId) == null) {
- Slog.w(TAG, "Unable to launch app "
+ String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
- + r.intent.getIntent() + ": user " + r.userId + " is stopped");
+ + r.intent.getIntent() + ": user " + r.userId + " is stopped";
+ Slog.w(TAG, msg);
bringDownServiceLocked(r, true);
- return false;
+ return msg;
}
// Service is now being launched, its package can't be stopped.
@@ -1018,7 +1020,7 @@
try {
app.addPackage(r.appInfo.packageName);
realStartServiceLocked(r, app);
- return true;
+ return null;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
@@ -1041,12 +1043,13 @@
if (app == null) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated)) == null) {
- Slog.w(TAG, "Unable to launch app "
+ String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
- + r.intent.getIntent() + ": process is bad");
+ + r.intent.getIntent() + ": process is bad";
+ Slog.w(TAG, msg);
bringDownServiceLocked(r, true);
- return false;
+ return msg;
}
if (isolated) {
r.isolatedProc = app;
@@ -1057,7 +1060,7 @@
mPendingServices.add(r);
}
- return true;
+ return null;
}
private final void requestServiceBindingsLocked(ServiceRecord r) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c2aa3a5..daed0a2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3585,7 +3585,7 @@
Slog.w(TAG, "Failed trying to unstop package "
+ packageName + ": " + e);
}
- if (isUserRunningLocked(user)) {
+ if (isUserRunningLocked(user, false)) {
forceStopPackageLocked(packageName, pkgUid);
}
}
@@ -3739,7 +3739,8 @@
private void forceStopUserLocked(int userId) {
forceStopPackageLocked(null, -1, false, false, true, false, userId);
Intent intent = new Intent(Intent.ACTION_USER_STOPPED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -7904,6 +7905,19 @@
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
+ intent = new Intent(Intent.ACTION_USER_STARTING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
+ broadcastIntentLocked(null, null, intent,
+ null, new IIntentReceiver.Stub() {
+ @Override
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser)
+ throws RemoteException {
+ }
+ }, 0, null, null,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -8879,7 +8893,7 @@
pw.println(" [-a] [-c] [-h] [cmd] ...");
pw.println(" cmd may be one of:");
pw.println(" a[ctivities]: activity stack state");
- pw.println(" b[roadcasts] [PACKAGE_NAME]: broadcast state");
+ pw.println(" b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state");
pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
pw.println(" o[om]: out of memory management");
@@ -9338,6 +9352,12 @@
pw.print(" User #"); pw.print(uss.mHandle.getIdentifier());
pw.print(": "); uss.dump("", pw);
}
+ pw.print(" mStartedUserArray: [");
+ for (int i=0; i<mStartedUserArray.length; i++) {
+ if (i > 0) pw.print(", ");
+ pw.print(mStartedUserArray[i]);
+ }
+ pw.println("]");
pw.print(" mUserLru: [");
for (int i=0; i<mUserLru.size(); i++) {
if (i > 0) pw.print(", ");
@@ -9707,6 +9727,9 @@
boolean onlyHistory = false;
if ("history".equals(dumpPackage)) {
+ if (opti < args.length && "-s".equals(args[opti])) {
+ dumpAll = false;
+ }
onlyHistory = true;
dumpPackage = null;
}
@@ -14106,11 +14129,14 @@
mWindowManager.startFreezingScreen(R.anim.screen_user_exit,
R.anim.screen_user_enter);
+ boolean needStart = false;
+
// If the user we are switching to is not currently started, then
// we need to start it now.
if (mStartedUsers.get(userId) == null) {
mStartedUsers.put(userId, new UserStartedState(new UserHandle(userId), false));
updateStartedUserArrayLocked();
+ needStart = true;
}
mCurrentUserId = userId;
@@ -14134,10 +14160,14 @@
// so we can just fairly silently bring the user back from
// the almost-dead.
uss.mState = UserStartedState.STATE_RUNNING;
+ updateStartedUserArrayLocked();
+ needStart = true;
} else if (uss.mState == UserStartedState.STATE_SHUTDOWN) {
// This means ACTION_SHUTDOWN has been sent, so we will
// need to treat this as a new boot of the user.
uss.mState = UserStartedState.STATE_BOOTING;
+ updateStartedUserArrayLocked();
+ needStart = true;
}
mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
@@ -14146,17 +14176,19 @@
oldUserId, userId, uss));
mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
- Intent intent = new Intent(Intent.ACTION_USER_STARTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null,
- false, false, MY_PID, Process.SYSTEM_UID, userId);
+ if (needStart) {
+ Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ broadcastIntentLocked(null, null, intent,
+ null, null, 0, null, null, null,
+ false, false, MY_PID, Process.SYSTEM_UID, userId);
+ }
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
if (userId != 0) {
- intent = new Intent(Intent.ACTION_USER_INITIALIZE);
+ Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntentLocked(null, null, intent, null,
new IIntentReceiver.Stub() {
@@ -14180,6 +14212,21 @@
getUserManagerLocked().userForeground(userId);
sendUserSwitchBroadcastsLocked(oldUserId, userId);
+ if (needStart) {
+ Intent intent = new Intent(Intent.ACTION_USER_STARTING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ broadcastIntentLocked(null, null, intent,
+ null, new IIntentReceiver.Stub() {
+ @Override
+ public void performReceive(Intent intent, int resultCode, String data,
+ Bundle extras, boolean ordered, boolean sticky, int sendingUser)
+ throws RemoteException {
+ }
+ }, 0, null, null,
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -14217,19 +14264,6 @@
null, null, 0, null, null,
android.Manifest.permission.MANAGE_USERS,
false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
- intent = new Intent(Intent.ACTION_USER_STARTING);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
- broadcastIntentLocked(null, null, intent,
- null, new IIntentReceiver.Stub() {
- @Override
- public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky, int sendingUser)
- throws RemoteException {
- }
- }, 0, null, null,
- android.Manifest.permission.INTERACT_ACROSS_USERS,
- false, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -14318,8 +14352,7 @@
void finishUserSwitch(UserStartedState uss) {
synchronized (this) {
- if ((uss.mState == UserStartedState.STATE_BOOTING
- || uss.mState == UserStartedState.STATE_SHUTDOWN)
+ if (uss.mState == UserStartedState.STATE_BOOTING
&& mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
uss.mState = UserStartedState.STATE_RUNNING;
final int userId = uss.mHandle.getIdentifier();
@@ -14410,6 +14443,7 @@
if (uss.mState != UserStartedState.STATE_STOPPING
&& uss.mState != UserStartedState.STATE_SHUTDOWN) {
uss.mState = UserStartedState.STATE_STOPPING;
+ updateStartedUserArrayLocked();
long ident = Binder.clearCallingIdentity();
try {
@@ -14514,7 +14548,7 @@
}
@Override
- public boolean isUserRunning(int userId) {
+ public boolean isUserRunning(int userId, boolean orStopped) {
if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: isUserRunning() from pid="
@@ -14525,13 +14559,19 @@
throw new SecurityException(msg);
}
synchronized (this) {
- return isUserRunningLocked(userId);
+ return isUserRunningLocked(userId, orStopped);
}
}
- boolean isUserRunningLocked(int userId) {
+ boolean isUserRunningLocked(int userId, boolean orStopped) {
UserStartedState state = mStartedUsers.get(userId);
- return state != null && state.mState != UserStartedState.STATE_STOPPING
+ if (state == null) {
+ return false;
+ }
+ if (orStopped) {
+ return true;
+ }
+ return state.mState != UserStartedState.STATE_STOPPING
&& state.mState != UserStartedState.STATE_SHUTDOWN;
}
@@ -14552,9 +14592,24 @@
}
private void updateStartedUserArrayLocked() {
- mStartedUserArray = new int[mStartedUsers.size()];
+ int num = 0;
for (int i=0; i<mStartedUsers.size(); i++) {
- mStartedUserArray[i] = mStartedUsers.keyAt(i);
+ UserStartedState uss = mStartedUsers.valueAt(i);
+ // This list does not include stopping users.
+ if (uss.mState != UserStartedState.STATE_STOPPING
+ && uss.mState != UserStartedState.STATE_SHUTDOWN) {
+ num++;
+ }
+ }
+ mStartedUserArray = new int[num];
+ num = 0;
+ for (int i=0; i<mStartedUsers.size(); i++) {
+ UserStartedState uss = mStartedUsers.valueAt(i);
+ if (uss.mState != UserStartedState.STATE_STOPPING
+ && uss.mState != UserStartedState.STATE_SHUTDOWN) {
+ mStartedUserArray[num] = mStartedUsers.keyAt(i);
+ num++;
+ }
}
}
diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java
index 95c22ec..f9630ae 100644
--- a/services/java/com/android/server/am/BroadcastQueue.java
+++ b/services/java/com/android/server/am/BroadcastQueue.java
@@ -54,6 +54,7 @@
static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
static final int MAX_BROADCAST_HISTORY = 25;
+ static final int MAX_BROADCAST_SUMMARY_HISTORY = 100;
final ActivityManagerService mService;
@@ -93,6 +94,12 @@
= new BroadcastRecord[MAX_BROADCAST_HISTORY];
/**
+ * Summary of historical data of past broadcasts, for debugging.
+ */
+ final Intent[] mBroadcastSummaryHistory
+ = new Intent[MAX_BROADCAST_SUMMARY_HISTORY];
+
+ /**
* Set when we current have a BROADCAST_INTENT_MSG in flight.
*/
boolean mBroadcastsScheduled = false;
@@ -922,6 +929,9 @@
MAX_BROADCAST_HISTORY-1);
r.finishTime = SystemClock.uptimeMillis();
mBroadcastHistory[0] = r;
+ System.arraycopy(mBroadcastSummaryHistory, 0, mBroadcastSummaryHistory, 1,
+ MAX_BROADCAST_SUMMARY_HISTORY-1);
+ mBroadcastSummaryHistory[0] = r.intent;
}
final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
@@ -1006,8 +1016,9 @@
}
}
+ int i;
boolean printed = false;
- for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
+ for (i=0; i<MAX_BROADCAST_HISTORY; i++) {
BroadcastRecord r = mBroadcastHistory[i];
if (r == null) {
break;
@@ -1028,11 +1039,44 @@
pw.print(i); pw.println(":");
r.dump(pw, " ");
} else {
- if (i >= 50) {
+ pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
+ pw.print(" ");
+ pw.println(r.intent.toShortString(false, true, true, false));
+ Bundle bundle = r.intent.getExtras();
+ if (bundle != null) {
+ pw.print(" extras: "); pw.println(bundle.toString());
+ }
+ }
+ }
+
+ if (dumpPackage == null) {
+ if (dumpAll) {
+ i = 0;
+ printed = false;
+ }
+ for (; i<MAX_BROADCAST_SUMMARY_HISTORY; i++) {
+ Intent intent = mBroadcastSummaryHistory[i];
+ if (intent == null) {
+ break;
+ }
+ if (!printed) {
+ if (needSep) {
+ pw.println();
+ }
+ needSep = true;
+ pw.println(" Historical broadcasts summary [" + mQueueName + "]:");
+ printed = true;
+ }
+ if (!dumpAll && i >= 50) {
pw.println(" ...");
break;
}
- pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
+ pw.print(" #"); pw.print(i); pw.print(": ");
+ pw.println(intent.toShortString(false, true, true, false));
+ Bundle bundle = intent.getExtras();
+ if (bundle != null) {
+ pw.print(" extras: "); pw.println(bundle.toString());
+ }
}
}
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index 85ec328..1cf5b9c 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -81,12 +81,10 @@
final long now = SystemClock.uptimeMillis();
pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId);
- pw.print(prefix); pw.println(intent);
- if (sticky) {
- Bundle bundle = intent.getExtras();
- if (bundle != null) {
- pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
- }
+ pw.print(prefix); pw.println(intent.toInsecureString());
+ Bundle bundle = intent.getExtras();
+ if (bundle != null) {
+ pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString());
}
pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" ");
pw.print(callerApp != null ? callerApp.toShortString() : "null");
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 0600f5c..b8d7286 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -6374,12 +6374,22 @@
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
+ /*
+ * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
+ * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
+ */
+ int userIdentifier = getUser().getIdentifier();
+ if (userIdentifier == UserHandle.USER_ALL
+ && ((flags & PackageManager.INSTALL_FROM_ADB) != 0)) {
+ userIdentifier = UserHandle.USER_OWNER;
+ }
+
/*
* Determine if we have any installed package verifiers. If we
* do, then we'll defer to them to verify the packages.
*/
final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage, getUser().getIdentifier());
+ : getPackageUid(mRequiredVerifierPackage, userIdentifier);
if (requiredUid != -1 && isVerificationEnabled(flags)) {
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index 85bf17a..b9085a4 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -127,6 +127,7 @@
private static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
+ private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
// Summarizes the user activity state.
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
@@ -1172,16 +1173,25 @@
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU
| WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+ }
}
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+ }
}
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
+ if (mWakefulness == WAKEFULNESS_AWAKE) {
+ mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
+ }
}
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
@@ -1339,7 +1349,7 @@
private boolean isBeingKeptAwakeLocked() {
return mStayOn
|| mProximityPositive
- || (mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0
+ || (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 0db9f19..037bfde 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2749,10 +2749,7 @@
}
}
- if (DEBUG_LAYOUT
- // TODO: Remove once b/7094175 is fixed
- || ((String)win.mAttrs.getTitle()).contains("Keyguard")
- ) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
+ if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
+ " " + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
@@ -9271,9 +9268,7 @@
"Reporting new frame to " + win + ": " + win.mCompatFrame);
int diff = 0;
boolean configChanged = win.isConfigChanged();
- if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION
- // TODO: Remove once b/7094175 is fixed
- || ((String)win.mAttrs.getTitle()).contains("Keyguard"))
+ if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
&& configChanged) {
Slog.i(TAG, "Sending new config to window " + win + ": "
+ winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
diff --git a/services/jni/com_android_server_power_PowerManagerService.cpp b/services/jni/com_android_server_power_PowerManagerService.cpp
index 75f77b9..23c33af 100644
--- a/services/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/jni/com_android_server_power_PowerManagerService.cpp
@@ -168,12 +168,14 @@
}
static void nativeSetInteractive(JNIEnv *env, jclass clazz, jboolean enable) {
- if (enable) {
- ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
- gPowerModule->setInteractive(gPowerModule, true);
- } else {
- ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
- gPowerModule->setInteractive(gPowerModule, false);
+ if (gPowerModule) {
+ if (enable) {
+ ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
+ gPowerModule->setInteractive(gPowerModule, true);
+ } else {
+ ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
+ gPowerModule->setInteractive(gPowerModule, false);
+ }
}
}
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index 4440145..9c727f9 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -98,6 +98,8 @@
static final int POOR_LINK_DETECTED = BASE + 21;
static final int GOOD_LINK_DETECTED = BASE + 22;
+ public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false;
+
/*
* RSSI levels as used by notification icon
* Level 4 -55 <= RSSI
@@ -345,13 +347,6 @@
// watchdog in an enabled state
putSettingsGlobalBoolean(contentResolver, Settings.Global.WIFI_WATCHDOG_ON, true);
- // disable poor network avoidance
- if (sWifiOnly) {
- logd("Disabling poor network avoidance for wi-fi only device");
- putSettingsGlobalBoolean(contentResolver,
- Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, false);
- }
-
WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
wwsm.start();
return wwsm;
@@ -441,8 +436,15 @@
private void updateSettings() {
if (DBG) logd("Updating secure settings");
- mPoorNetworkDetectionEnabled = getSettingsGlobalBoolean(mContentResolver,
- Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, true);
+ // disable poor network avoidance
+ if (sWifiOnly) {
+ logd("Disabling poor network avoidance for wi-fi only device");
+ mPoorNetworkDetectionEnabled = false;
+ } else {
+ mPoorNetworkDetectionEnabled = getSettingsGlobalBoolean(mContentResolver,
+ Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
+ DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED);
+ }
}
/**