diff options
25 files changed, 562 insertions, 245 deletions
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 @@ package android.hardware; 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 @@ public class Camera { * 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 @@ public class Camera { * @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 3bbdf36..3c4a8fe 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4052,7 +4052,20 @@ public final class Settings { * @return true if the provider is enabled */ public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) { - String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED); + return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId()); + } + + /** + * Helper method for determining if a location provider is enabled. + * @param cr the content resolver to use + * @param provider the location provider to query + * @param userId the userId to query + * @return true if the provider is enabled + * @hide + */ + public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) { + String allowedProviders = Settings.Secure.getStringForUser(cr, + LOCATION_PROVIDERS_ALLOWED, userId); return TextUtils.delimitedStringContains(allowedProviders, ',', provider); } @@ -4064,6 +4077,19 @@ public final class Settings { */ public static final void setLocationProviderEnabled(ContentResolver cr, String provider, boolean enabled) { + setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId()); + } + + /** + * Thread-safe method for enabling or disabling a single location provider. + * @param cr the content resolver to use + * @param provider the location provider to enable or disable + * @param enabled true if the provider should be enabled + * @param userId the userId for which to enable/disable providers + * @hide + */ + public static final void setLocationProviderEnabledForUser(ContentResolver cr, + String provider, boolean enabled, int userId) { // to ensure thread safety, we write the provider name with a '+' or '-' // and let the SettingsProvider handle it rather than reading and modifying // the list of enabled providers. @@ -4072,7 +4098,8 @@ public final class Settings { } else { provider = "-" + provider; } - putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider); + putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider, + userId); } } @@ -5294,6 +5321,7 @@ public final class Settings { 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/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 @@ public class ScaleGestureDetector { 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/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 @@ static JNINativeMethod camMethods[] = { { "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 @@ static JNINativeMethod camMethods[] = { { "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/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.database.Cursor; 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { // 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { getContentResolver().insert(destination, contentValues); } - if (DEBUG || true) { + if (DEBUG) { Log.d(TAG, "Restored setting: " + destination + " : "+ key + "=" + value); } } @@ -731,17 +792,6 @@ public class SettingsBackupAgent extends BackupAgentHelper { } - 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { } } - 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/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 3351e61..9307f37 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -447,6 +447,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Screenshot trigger states // Time to volume and power must be pressed within this interval of each other. private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150; + // Increase the chord delay when taking a screenshot from the keyguard + private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; private boolean mScreenshotChordEnabled; private boolean mVolumeDownKeyTriggered; private long mVolumeDownKeyTime; @@ -669,12 +671,21 @@ public class PhoneWindowManager implements WindowManagerPolicy { mVolumeDownKeyConsumedByScreenshotChord = true; cancelPendingPowerKeyAction(); - mHandler.postDelayed(mScreenshotChordLongPress, - ViewConfiguration.getGlobalActionKeyTimeout()); + mHandler.postDelayed(mScreenshotChordLongPress, getScreenshotChordLongPressDelay()); } } } + private long getScreenshotChordLongPressDelay() { + if (mKeyguardMediator.isShowing()) { + // Double the time it takes to take a screenshot from the keyguard + return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * + ViewConfiguration.getGlobalActionKeyTimeout()); + } else { + return ViewConfiguration.getGlobalActionKeyTimeout(); + } + } + private void cancelPendingScreenshotChordAction() { mHandler.removeCallbacks(mScreenshotChordLongPress); } 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.content.res.Resources; 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.MotionEvent; 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 @@ public class KeyguardHostView extends KeyguardViewBase { 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 @@ public class KeyguardHostView extends KeyguardViewBase { 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 @@ public class KeyguardHostView extends KeyguardViewBase { mAppWidgetHost.startListening(); maybePopulateWidgets(); disableStatusViewInteraction(); - showAppropriateWidgetPage(); + post(mSwitchPageRunnable); } private void disableStatusViewInteraction() { @@ -712,7 +722,7 @@ public class KeyguardHostView extends KeyguardViewBase { 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 @@ public class KeyguardHostView extends KeyguardViewBase { 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 @@ public class KeyguardHostView extends KeyguardViewBase { // 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 @@ public class KeyguardHostView extends KeyguardViewBase { } } + Runnable mSwitchPageRunnable = new Runnable() { + @Override + public void run() { + showAppropriateWidgetPage(); + } + }; + + 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() { - int page = mAppWidgetContainer.indexOfChild(findViewById(R.id.keyguard_status_view)); - if (mAppWidgetContainer.indexOfChild(mTransportControl) != -1) { - page = mAppWidgetContainer.indexOfChild(mTransportControl); + + // 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(page); + 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.content.pm.ResolveInfo; 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 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri } 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.util.Log; 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements } 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements 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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements @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 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements } 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 @@ import com.android.internal.widget.LockPatternUtils; * 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 @@ public class KeyguardViewManager { 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 @@ public class KeyguardViewManager { 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 e73d599..c5016e6 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -226,7 +226,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run updateProvidersLocked(); } } - }); + }, UserHandle.USER_ALL); mPackageMonitor.register(mContext, Looper.myLooper(), true); // listen for user change @@ -289,7 +289,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run mContext, LocationManager.NETWORK_PROVIDER, NETWORK_LOCATION_SERVICE_ACTION, - providerPackageNames, mLocationHandler); + providerPackageNames, mLocationHandler, mCurrentUserId); if (networkProvider != null) { mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider); mProxyProviders.add(networkProvider); @@ -303,18 +303,20 @@ public class LocationManagerService extends ILocationManager.Stub implements Run mContext, LocationManager.FUSED_PROVIDER, FUSED_LOCATION_SERVICE_ACTION, - providerPackageNames, mLocationHandler); + providerPackageNames, mLocationHandler, mCurrentUserId); if (fusedLocationProvider != null) { 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")); } // bind to geocoder provider - mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames); + mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames, + mCurrentUserId); if (mGeocodeProvider == null) { Slog.e(TAG, "no geocoder provider found"); } @@ -326,11 +328,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Run */ private void switchUser(int userId) { mBlacklist.switchUser(userId); - //Log.d("LocationManagerService", "switchUser(" + mCurrentUserId + " -> " + userId + ")"); // TODO: remove this synchronized (mLock) { - // TODO: inform previous user's Receivers that they will no longer receive updates + mLastLocation.clear(); + for (LocationProviderInterface p : mProviders) { + updateProviderListenersLocked(p.getName(), false, mCurrentUserId); + p.switchUser(userId); + } mCurrentUserId = userId; - // TODO: inform new user's Receivers that they are back on the update train + updateProvidersLocked(); } } @@ -587,7 +592,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } - private boolean isAllowedBySettingsLocked(String provider) { + private boolean isAllowedBySettingsLocked(String provider, int userId) { + if (userId != mCurrentUserId) { + return false; + } if (mEnabledProviders.contains(provider)) { return true; } @@ -597,7 +605,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Use system settings ContentResolver resolver = mContext.getContentResolver(); - return Settings.Secure.isLocationProviderEnabled(resolver, provider); + return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId); } /** @@ -695,24 +703,30 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public List<String> getProviders(Criteria criteria, boolean enabledOnly) { ArrayList<String> out; - synchronized (mLock) { - out = new ArrayList<String>(mProviders.size()); - for (LocationProviderInterface provider : mProviders) { - String name = provider.getName(); - if (LocationManager.FUSED_PROVIDER.equals(name)) { - continue; - } - if (isAllowedProviderSafe(name)) { - if (enabledOnly && !isAllowedBySettingsLocked(name)) { + int callingUserId = UserHandle.getCallingUserId(); + long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + out = new ArrayList<String>(mProviders.size()); + for (LocationProviderInterface provider : mProviders) { + String name = provider.getName(); + if (LocationManager.FUSED_PROVIDER.equals(name)) { continue; } - if (criteria != null && !LocationProvider.propertiesMeetCriteria( - name, provider.getProperties(), criteria)) { - continue; + if (isAllowedProviderSafe(name)) { + if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) { + continue; + } + if (criteria != null && !LocationProvider.propertiesMeetCriteria( + name, provider.getProperties(), criteria)) { + continue; + } + out.add(name); } - out.add(name); } } + } finally { + Binder.restoreCallingIdentity(identity); } if (D) Log.d(TAG, "getProviders()=" + out); @@ -778,12 +792,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run LocationProviderInterface p = mProviders.get(i); boolean isEnabled = p.isEnabled(); String name = p.getName(); - boolean shouldBeEnabled = isAllowedBySettingsLocked(name); + boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId); if (isEnabled && !shouldBeEnabled) { - updateProviderListenersLocked(name, false); + updateProviderListenersLocked(name, false, mCurrentUserId); changesMade = true; } else if (!isEnabled && shouldBeEnabled) { - updateProviderListenersLocked(name, true); + updateProviderListenersLocked(name, true, mCurrentUserId); changesMade = true; } } @@ -793,7 +807,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - private void updateProviderListenersLocked(String provider, boolean enabled) { + private void updateProviderListenersLocked(String provider, boolean enabled, int userId) { int listeners = 0; LocationProviderInterface p = mProvidersByName.get(provider); @@ -806,14 +820,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run final int N = records.size(); for (int i = 0; i < N; i++) { UpdateRecord record = records.get(i); - // Sends a notification message to the receiver - if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { - if (deadReceivers == null) { - deadReceivers = new ArrayList<Receiver>(); + if (UserHandle.getUserId(record.mReceiver.mUid) == userId) { + // Sends a notification message to the receiver + if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { + if (deadReceivers == null) { + deadReceivers = new ArrayList<Receiver>(); + } + deadReceivers.add(record.mReceiver); } - deadReceivers.add(record.mReceiver); + listeners++; } - listeners++; } } @@ -843,12 +859,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (records != null) { for (UpdateRecord record : records) { - LocationRequest locationRequest = record.mRequest; - - providerRequest.locationRequests.add(locationRequest); - if (locationRequest.getInterval() < providerRequest.interval) { - providerRequest.reportLocation = true; - providerRequest.interval = locationRequest.getInterval(); + if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { + LocationRequest locationRequest = record.mRequest; + providerRequest.locationRequests.add(locationRequest); + if (locationRequest.getInterval() < providerRequest.interval) { + providerRequest.reportLocation = true; + providerRequest.interval = locationRequest.getInterval(); + } } } @@ -860,9 +877,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // under that threshold. long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; for (UpdateRecord record : records) { - LocationRequest locationRequest = record.mRequest; - if (locationRequest.getInterval() <= thresholdInterval) { - worksource.add(record.mReceiver.mUid); + if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { + LocationRequest locationRequest = record.mRequest; + if (locationRequest.getInterval() <= thresholdInterval) { + worksource.add(record.mReceiver.mUid); + } } } } @@ -1084,7 +1103,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run oldRecord.disposeLocked(false); } - boolean isProviderEnabled = isAllowedBySettingsLocked(name); + boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid)); if (isProviderEnabled) { applyRequirementsLocked(name); } else { @@ -1141,7 +1160,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // update provider for (String provider : providers) { // If provider is already disabled, don't need to do anything - if (!isAllowedBySettingsLocked(provider)) { + if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) { continue; } @@ -1156,36 +1175,41 @@ public class LocationManagerService extends ILocationManager.Stub implements Run String perm = checkPermissionAndRequest(request); checkPackageName(packageName); - if (mBlacklist.isBlacklisted(packageName)) { - if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + - packageName); - return null; - } - - synchronized (mLock) { - // Figure out the provider. Either its explicitly request (deprecated API's), - // or use the fused provider - String name = request.getProvider(); - if (name == null) name = LocationManager.FUSED_PROVIDER; - LocationProviderInterface provider = mProvidersByName.get(name); - if (provider == null) return null; - - if (!isAllowedBySettingsLocked(name)) return null; - - Location location = mLastLocation.get(name); - if (location == null) { + long identity = Binder.clearCallingIdentity(); + try { + if (mBlacklist.isBlacklisted(packageName)) { + if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + + packageName); return null; } - if (ACCESS_FINE_LOCATION.equals(perm)) { - return location; - } else { - Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); - if (noGPSLocation != null) { - return mLocationFudger.getOrCreate(noGPSLocation); + + synchronized (mLock) { + // Figure out the provider. Either its explicitly request (deprecated API's), + // or use the fused provider + String name = request.getProvider(); + if (name == null) name = LocationManager.FUSED_PROVIDER; + LocationProviderInterface provider = mProvidersByName.get(name); + if (provider == null) return null; + + if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null; + + Location location = mLastLocation.get(name); + if (location == null) { + return null; + } + if (ACCESS_FINE_LOCATION.equals(perm)) { + return location; + } else { + Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); + if (noGPSLocation != null) { + return mLocationFudger.getOrCreate(noGPSLocation); + } } } + return null; + } finally { + Binder.restoreCallingIdentity(identity); } - return null; } @Override @@ -1321,11 +1345,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run "\" provider requires ACCESS_FINE_LOCATION permission"); } - synchronized (mLock) { - LocationProviderInterface p = mProvidersByName.get(provider); - if (p == null) return false; + long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + LocationProviderInterface p = mProvidersByName.get(provider); + if (p == null) return false; - return isAllowedBySettingsLocked(provider); + return isAllowedBySettingsLocked(provider, mCurrentUserId); + } + } finally { + Binder.restoreCallingIdentity(identity); } } @@ -1461,6 +1490,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run Receiver receiver = r.mReceiver; boolean receiverDead = false; + int receiverUserId = UserHandle.getUserId(receiver.mUid); + if (receiverUserId != mCurrentUserId) { + if (D) { + Log.d(TAG, "skipping loc update for background user " + receiverUserId + + " (current user: " + mCurrentUserId + ", app: " + + receiver.mPackageName + ")"); + } + continue; + } + if (mBlacklist.isBlacklisted(receiver.mPackageName)) { if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + receiver.mPackageName); @@ -1551,7 +1590,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } synchronized (mLock) { - if (isAllowedBySettingsLocked(provider)) { + if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { handleLocationChangedLocked(location, passive); } } diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/java/com/android/server/ServiceWatcher.java index e99949b..5598b0a 100644 --- a/services/java/com/android/server/ServiceWatcher.java +++ b/services/java/com/android/server/ServiceWatcher.java @@ -27,6 +27,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.os.Handler; import android.os.IBinder; +import android.os.UserHandle; import android.util.Log; import com.android.internal.content.PackageMonitor; @@ -58,15 +59,17 @@ public class ServiceWatcher implements ServiceConnection { private IBinder mBinder; // connected service private String mPackageName; // current best package private int mVersion; // current best version + private int mCurrentUserId; public ServiceWatcher(Context context, String logTag, String action, - List<String> initialPackageNames, Runnable newServiceWork, Handler handler) { + List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) { mContext = context; mTag = logTag; mAction = action; mPm = mContext.getPackageManager(); mNewServiceWork = newServiceWork; mHandler = handler; + mCurrentUserId = userId; mSignatureSets = new ArrayList<HashSet<Signature>>(); for (int i=0; i < initialPackageNames.size(); i++) { @@ -85,9 +88,11 @@ public class ServiceWatcher implements ServiceConnection { } public boolean start() { - if (!bindBestPackage(null)) return false; + synchronized (mLock) { + if (!bindBestPackageLocked(null)) return false; + } - mPackageMonitor.register(mContext, null, true); + mPackageMonitor.register(mContext, null, UserHandle.ALL, true); return true; } @@ -98,13 +103,13 @@ public class ServiceWatcher implements ServiceConnection { * is null. * Return true if a new package was found to bind to. */ - private boolean bindBestPackage(String justCheckThisPackage) { + private boolean bindBestPackageLocked(String justCheckThisPackage) { Intent intent = new Intent(mAction); if (justCheckThisPackage != null) { intent.setPackage(justCheckThisPackage); } - List<ResolveInfo> rInfos = mPm.queryIntentServices(new Intent(mAction), - PackageManager.GET_META_DATA); + List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(new Intent(mAction), + PackageManager.GET_META_DATA, mCurrentUserId); int bestVersion = Integer.MIN_VALUE; String bestPackage = null; for (ResolveInfo rInfo : rInfos) { @@ -141,36 +146,32 @@ public class ServiceWatcher implements ServiceConnection { (bestPackage == null ? "no new best package" : "new best packge: " + bestPackage))); if (bestPackage != null) { - bindToPackage(bestPackage, bestVersion); + bindToPackageLocked(bestPackage, bestVersion); return true; } return false; } - private void unbind() { + private void unbindLocked() { String pkg; - synchronized (mLock) { - pkg = mPackageName; - mPackageName = null; - mVersion = Integer.MIN_VALUE; - } + pkg = mPackageName; + mPackageName = null; + mVersion = Integer.MIN_VALUE; if (pkg != null) { if (D) Log.d(mTag, "unbinding " + pkg); mContext.unbindService(this); } } - private void bindToPackage(String packageName, int version) { - unbind(); + private void bindToPackageLocked(String packageName, int version) { + unbindLocked(); Intent intent = new Intent(mAction); intent.setPackage(packageName); - synchronized (mLock) { - mPackageName = packageName; - mVersion = version; - } + mPackageName = packageName; + mVersion = version; if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ")"); mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND - | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE); + | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId); } private boolean isSignatureMatch(Signature[] signatures) { @@ -197,31 +198,37 @@ public class ServiceWatcher implements ServiceConnection { */ @Override public void onPackageUpdateFinished(String packageName, int uid) { - if (packageName.equals(mPackageName)) { - // package updated, make sure to rebind - unbind(); + synchronized (mLock) { + if (packageName.equals(mPackageName)) { + // package updated, make sure to rebind + unbindLocked(); + } + // check the updated package in case it is better + bindBestPackageLocked(packageName); } - // check the updated package in case it is better - bindBestPackage(packageName); } @Override public void onPackageAdded(String packageName, int uid) { - if (packageName.equals(mPackageName)) { - // package updated, make sure to rebind - unbind(); + synchronized (mLock) { + if (packageName.equals(mPackageName)) { + // package updated, make sure to rebind + unbindLocked(); + } + // check the new package is case it is better + bindBestPackageLocked(packageName); } - // check the new package is case it is better - bindBestPackage(packageName); } @Override public void onPackageRemoved(String packageName, int uid) { - if (packageName.equals(mPackageName)) { - unbind(); - // the currently bound package was removed, - // need to search for a new package - bindBestPackage(null); + synchronized (mLock) { + if (packageName.equals(mPackageName)) { + unbindLocked(); + // the currently bound package was removed, + // need to search for a new package + bindBestPackageLocked(null); + } } } }; @@ -271,4 +278,12 @@ public class ServiceWatcher implements ServiceConnection { return mBinder; } } + + public void switchUser(int userId) { + synchronized (mLock) { + unbindLocked(); + mCurrentUserId = userId; + bindBestPackageLocked(null); + } + } } diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java index 7d030e9..f5cc59f 100644 --- a/services/java/com/android/server/location/GeocoderProxy.java +++ b/services/java/com/android/server/location/GeocoderProxy.java @@ -21,6 +21,7 @@ import android.location.Address; import android.location.GeocoderParams; import android.location.IGeocodeProvider; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import com.android.server.ServiceWatcher; @@ -38,8 +39,8 @@ public class GeocoderProxy { private final ServiceWatcher mServiceWatcher; public static GeocoderProxy createAndBind(Context context, - List<String> initialPackageNames) { - GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames); + List<String> initialPackageNames, int userId) { + GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames, userId); if (proxy.bind()) { return proxy; } else { @@ -47,11 +48,11 @@ public class GeocoderProxy { } } - public GeocoderProxy(Context context, List<String> initialPackageNames) { + public GeocoderProxy(Context context, List<String> initialPackageNames, int userId) { mContext = context; mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames, - null, null); + null, null, userId); } private boolean bind () { diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java index a254d74..c272da4 100755 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/java/com/android/server/location/GpsLocationProvider.java @@ -783,6 +783,11 @@ public class GpsLocationProvider implements LocationProviderInterface { sendMessage(SET_REQUEST, 0, new GpsRequest(request, source)); } + @Override + public void switchUser(int userId) { + // nothing to do here + } + private void handleSetRequest(ProviderRequest request, WorkSource source) { if (DEBUG) Log.d(TAG, "setRequest " + request); diff --git a/services/java/com/android/server/location/LocationProviderInterface.java b/services/java/com/android/server/location/LocationProviderInterface.java index 6f09232..80e71f1 100644 --- a/services/java/com/android/server/location/LocationProviderInterface.java +++ b/services/java/com/android/server/location/LocationProviderInterface.java @@ -38,6 +38,8 @@ public interface LocationProviderInterface { public boolean isEnabled(); public void setRequest(ProviderRequest request, WorkSource source); + public void switchUser(int userId); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args); // --- deprecated (but still supported) --- diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java index 7faf72c..dd2e71c 100644 --- a/services/java/com/android/server/location/LocationProviderProxy.java +++ b/services/java/com/android/server/location/LocationProviderProxy.java @@ -25,6 +25,7 @@ import android.location.LocationProvider; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; +import android.os.UserHandle; import android.os.WorkSource; import android.util.Log; @@ -54,9 +55,9 @@ public class LocationProviderProxy implements LocationProviderInterface { private WorkSource mWorksource = new WorkSource(); public static LocationProviderProxy createAndBind(Context context, String name, String action, - List<String> initialPackageNames, Handler handler) { + List<String> initialPackageNames, Handler handler, int userId) { LocationProviderProxy proxy = new LocationProviderProxy(context, name, action, - initialPackageNames, handler); + initialPackageNames, handler, userId); if (proxy.bind()) { return proxy; } else { @@ -65,11 +66,11 @@ public class LocationProviderProxy implements LocationProviderInterface { } private LocationProviderProxy(Context context, String name, String action, - List<String> initialPackageNames, Handler handler) { + List<String> initialPackageNames, Handler handler, int userId) { mContext = context; mName = name; mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames, - mNewServiceWork, handler); + mNewServiceWork, handler, userId); } private boolean bind () { @@ -211,6 +212,11 @@ public class LocationProviderProxy implements LocationProviderInterface { } @Override + public void switchUser(int userId) { + mServiceWatcher.switchUser(userId); + } + + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.append("REMOTE SERVICE"); pw.append(" name=").append(mName); diff --git a/services/java/com/android/server/location/MockProvider.java b/services/java/com/android/server/location/MockProvider.java index 36c43ff..1194cbc 100644 --- a/services/java/com/android/server/location/MockProvider.java +++ b/services/java/com/android/server/location/MockProvider.java @@ -156,6 +156,11 @@ public class MockProvider implements LocationProviderInterface { public void setRequest(ProviderRequest request, WorkSource source) { } @Override + public void switchUser(int userId) { + // nothing to do here + } + + @Override public boolean sendExtraCommand(String command, Bundle extras) { return false; } diff --git a/services/java/com/android/server/location/PassiveProvider.java b/services/java/com/android/server/location/PassiveProvider.java index 71bae07..734c572 100644 --- a/services/java/com/android/server/location/PassiveProvider.java +++ b/services/java/com/android/server/location/PassiveProvider.java @@ -96,6 +96,11 @@ public class PassiveProvider implements LocationProviderInterface { mReportLocation = request.reportLocation; } + @Override + public void switchUser(int userId) { + // nothing to do here + } + public void updateLocation(Location location) { if (mReportLocation) { try { 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 @@ public class PackageManagerService extends IPackageManager.Stub { 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 @@ public final class PowerManagerService extends IPowerManager.Stub 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 @@ public final class PowerManagerService extends IPowerManager.Stub 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 @@ public final class PowerManagerService extends IPowerManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } } - 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 @@ public class WindowManagerService extends IWindowManager.Stub "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 nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameS } 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 @@ public class WifiWatchdogStateMachine extends StateMachine { 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 @@ public class WifiWatchdogStateMachine extends StateMachine { // 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 @@ public class WifiWatchdogStateMachine extends StateMachine { 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); + } } /** |
