Merge "Defer wifi bounce following restore for 1 minute..." into jb-mr1-dev
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/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/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/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/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..d25444f 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;
@@ -359,6 +359,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/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);