diff options
63 files changed, 538 insertions, 191 deletions
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 5cde65c..03e0c0f 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -247,7 +247,6 @@ public class AccountManagerService } public void systemReady() { - initUser(UserHandle.USER_OWNER); } private UserManager getUserManager() { diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 58df167..bb0c686 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -55,6 +55,7 @@ import android.text.format.Time; import android.util.EventLog; import android.util.Log; import android.util.Pair; +import android.util.Slog; import com.android.internal.R; import com.android.internal.util.IndentingPrintWriter; @@ -311,13 +312,10 @@ public class SyncManager { if (userId == UserHandle.USER_NULL) return; if (Intent.ACTION_USER_REMOVED.equals(action)) { - Log.i(TAG, "User removed: u" + userId); onUserRemoved(userId); } else if (Intent.ACTION_USER_STARTING.equals(action)) { - Log.i(TAG, "User starting: u" + userId); onUserStarting(userId); } else if (Intent.ACTION_USER_STOPPING.equals(action)) { - Log.i(TAG, "User stopping: u" + userId); onUserStopping(userId); } } @@ -338,6 +336,10 @@ public class SyncManager { } } + /** + * Should only be created after {@link ContentService#systemReady()} so that + * {@link PackageManager} is ready to query. + */ public SyncManager(Context context, boolean factoryTest) { // Initialize the SyncStorageEngine first, before registering observers // and creating threads and so on; it may fail if the disk is full. @@ -441,9 +443,6 @@ public class SyncManager { UserHandle.ALL, new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION), null, null); - - // do this synchronously to ensure we have the accounts before this call returns - onUserStarting(UserHandle.USER_OWNER); } // Pick a random second in a day to seed all periodic syncs diff --git a/core/java/android/content/SyncQueue.java b/core/java/android/content/SyncQueue.java index 14bfc5b..c9a325e 100644 --- a/core/java/android/content/SyncQueue.java +++ b/core/java/android/content/SyncQueue.java @@ -51,8 +51,6 @@ public class SyncQueue { public SyncQueue(SyncStorageEngine syncStorageEngine, final SyncAdaptersCache syncAdapters) { mSyncStorageEngine = syncStorageEngine; mSyncAdapters = syncAdapters; - - addPendingOperations(UserHandle.USER_OWNER); } public void addPendingOperations(int userId) { diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 69e1de9..ce5f163 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -110,7 +110,7 @@ import java.util.concurrent.atomic.AtomicInteger; * <h2>The 4 steps</h2> * <p>When an asynchronous task is executed, the task goes through 4 steps:</p> * <ol> - * <li>{@link #onPreExecute()}, invoked on the UI thread immediately after the task + * <li>{@link #onPreExecute()}, invoked on the UI thread before the task * is executed. This step is normally used to setup the task, for instance by * showing a progress bar in the user interface.</li> * <li>{@link #doInBackground}, invoked on the background thread diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 7ce3042..67452ec 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -887,11 +887,13 @@ public final class ViewRootImpl implements ViewParent, // Intersect with the bounds of the window to skip // updates that lie outside of the visible region final float appScale = mAttachInfo.mApplicationScale; - localDirty.intersect(0, 0, - (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); - - if (!mWillDrawSoon) { - scheduleTraversals(); + if (localDirty.intersect(0, 0, + (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f))) { + if (!mWillDrawSoon) { + scheduleTraversals(); + } + } else { + localDirty.setEmpty(); } return null; diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 1b71b43..5d306d2 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -829,7 +829,6 @@ static void android_view_GLES20Canvas_clearLayerTexture(JNIEnv* env, jobject cla static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz, Layer* layer, SkMatrix* matrix) { - layer->getTransform().load(*matrix); } diff --git a/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png Binary files differnew file mode 100644 index 0000000..35f27df --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png diff --git a/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png Binary files differnew file mode 100644 index 0000000..f9c8678 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png diff --git a/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png Binary files differnew file mode 100644 index 0000000..4cc0ee8 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index c93008d..3e8892b 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1418,7 +1418,7 @@ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou tablet te ontsluit deur middel van \'n e-posrekening."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string> <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou foon te ontsluit deur middel van \'n e-posrekening."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string> <string name="safe_media_volume_warning" product="default" msgid="7382971871993371648">"Moet volume bo veilige vlak verhoog word?"\n"Deur vir lang tydperke op hoƫ volume te luister, kan jou gehoor beskadig."</string> - <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Hou twee vingers in om toeganklikheid te aktiveer."</string> + <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Hou aan met twee vingers inhou om toeganklikheid te aktiveer."</string> <string name="accessibility_enabled" msgid="1381972048564547685">"Toeganklikheid geaktiveer."</string> <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Toeganklikheid gekanselleer."</string> <string name="user_switched" msgid="3768006783166984410">"Huidige gebruiker <xliff:g id="NAME">%1$s</xliff:g> ."</string> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 72de22c..f8dbd84 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3821,6 +3821,13 @@ <!-- Title text to show within the overlay. [CHAR LIMIT=50] --> <string name="display_manager_overlay_display_title"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="width">%2$d</xliff:g>x<xliff:g id="height">%3$d</xliff:g>, <xliff:g id="dpi">%4$d</xliff:g> dpi</string> + <!-- Title of the notification to indicate an active wifi display connection. [CHAR LIMIT=50] --> + <string name="wifi_display_notification_title">Wireless display is connected</string> + <!-- Message of the notification to indicate an active wifi display connection. [CHAR LIMIT=80] --> + <string name="wifi_display_notification_message">This screen is showing on another device</string> + <!-- Label of a button to disconnect an active wifi display connection. [CHAR LIMIT=25] --> + <string name="wifi_display_notification_disconnect">Disconnect</string> + <!-- Keyguard strings --> <!-- Label shown on emergency call button in keyguard --> <string name="kg_emergency_call_label">Emergency call</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e76b67b..b3af161 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1486,6 +1486,7 @@ <java-symbol type="bool" name="show_ongoing_ime_switcher" /> <java-symbol type="color" name="config_defaultNotificationColor" /> <java-symbol type="drawable" name="ic_notification_ime_default" /> + <java-symbol type="drawable" name="ic_notify_wifidisplay" /> <java-symbol type="drawable" name="stat_notify_car_mode" /> <java-symbol type="drawable" name="stat_notify_disabled" /> <java-symbol type="drawable" name="stat_notify_disk_full" /> @@ -1621,6 +1622,9 @@ <java-symbol type="string" name="vpn_lockdown_error" /> <java-symbol type="string" name="vpn_lockdown_reset" /> <java-symbol type="string" name="wallpaper_binding_label" /> + <java-symbol type="string" name="wifi_display_notification_title" /> + <java-symbol type="string" name="wifi_display_notification_message" /> + <java-symbol type="string" name="wifi_display_notification_disconnect" /> <java-symbol type="style" name="Theme.Dialog.AppError" /> <java-symbol type="style" name="Theme.Toast" /> <java-symbol type="xml" name="storage_list" /> diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml index 05f8b39..1bbc7df 100644 --- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml +++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml @@ -72,5 +72,6 @@ <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> + <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" /> </manifest> diff --git a/data/fonts/DroidNaskh-Bold.ttf b/data/fonts/DroidNaskh-Bold.ttf Binary files differindex 692b796..14d8768 100644 --- a/data/fonts/DroidNaskh-Bold.ttf +++ b/data/fonts/DroidNaskh-Bold.ttf diff --git a/data/fonts/DroidNaskh-Regular.ttf b/data/fonts/DroidNaskh-Regular.ttf Binary files differindex da9a45f..03662f2 100644 --- a/data/fonts/DroidNaskh-Regular.ttf +++ b/data/fonts/DroidNaskh-Regular.ttf diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 69be317..448e3da 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -209,6 +209,9 @@ struct Layer { } inline void allocateTexture(GLenum format, GLenum storage) { +#if DEBUG_LAYERS + ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight()); +#endif glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL); } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 406d5e9..b6be5b3 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -895,12 +895,6 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { float alpha = layer->getAlpha() / 255.0f; - mat4& transform = layer->getTransform(); - if (!transform.isIdentity()) { - save(0); - mSnapshot->transform->multiply(transform); - } - setupDraw(); if (layer->getRenderTarget() == GL_TEXTURE_2D) { setupDrawWithTexture(); @@ -937,10 +931,6 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); finishDrawTexture(); - - if (!transform.isIdentity()) { - restore(); - } } void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { @@ -2792,12 +2782,24 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain return DrawGlInfo::kStatusDone; } + mat4* transform = NULL; + if (layer->isTextureLayer()) { + transform = &layer->getTransform(); + if (!transform->isIdentity()) { + save(0); + mSnapshot->transform->multiply(*transform); + } + } + Rect transformed; Rect clip; const bool rejected = quickRejectNoScissor(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip); if (rejected) { + if (transform && !transform->isIdentity()) { + restore(); + } return DrawGlInfo::kStatusDone; } @@ -2858,6 +2860,10 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain } } + if (transform && !transform->isIdentity()) { + restore(); + } + return DrawGlInfo::kStatusDrew; } diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 7fb86ee..10d112a 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -74,8 +74,6 @@ void TextureCache::init() { INIT_LOGD(" Maximum texture dimension is %d pixels", mMaxTextureSize); mDebugEnabled = readDebugLevel() & kDebugCaches; - - mHasNPot = false; //Caches::getInstance().extensions.hasNPot(); } /////////////////////////////////////////////////////////////////////////////// @@ -219,11 +217,15 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege return; } + // We could also enable mipmapping if both bitmap dimensions are powers + // of 2 but we'd have to deal with size changes. Let's keep this simple + const bool canMipMap = Caches::getInstance().extensions.hasNPot(); + // If the texture had mipmap enabled but not anymore, // force a glTexImage2D to discard the mipmap levels const bool resize = !regenerate || bitmap->width() != int(texture->width) || bitmap->height() != int(texture->height) || - (regenerate && mHasNPot && texture->mipMap && !bitmap->hasHardwareMipMap()); + (regenerate && canMipMap && texture->mipMap && !bitmap->hasHardwareMipMap()); if (!regenerate) { glGenTextures(1, &texture->id); @@ -267,7 +269,7 @@ void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool rege break; } - if (mHasNPot) { + if (canMipMap) { texture->mipMap = bitmap->hasHardwareMipMap(); if (texture->mipMap) { glGenerateMipmap(GL_TEXTURE_2D); diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 8e19092..31a2e3d 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -138,7 +138,6 @@ private: float mFlushRate; - bool mHasNPot; bool mDebugEnabled; Vector<SkBitmap*> mGarbage; 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 3464924..1c60401 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java @@ -117,6 +117,7 @@ public class MediaPlayerPerformance extends ActivityInstrumentationTestCase2<Med } mMemWriter = new BufferedWriter(new FileWriter (new File(MEDIA_MEMORY_OUTPUT), true)); + mMemWriter.write(this.getName() + "\n"); } @Override diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml index 5a5769b..f7b1d78 100644 --- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml +++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml @@ -21,6 +21,8 @@ <ImageView android:id="@+id/brightness_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:paddingRight="10dp" android:src="@drawable/ic_qs_brightness_auto_off" diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml index 2d1bda4..59544f4 100644 --- a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml +++ b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml @@ -170,7 +170,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_sysbar_quicksettings" - android:contentDescription="@string/accessibility_settings_button" + android:contentDescription="@string/accessibility_desc_quick_settings" /> <ImageView diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 57d2ed3..9f0bcf5 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -185,6 +185,16 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener final Activity activity = (Activity) RecentsPanelView.this.getContext(); final SystemUIApplication app = (SystemUIApplication) activity.getApplication(); if (app.isWaitingForWindowAnimationStart()) { + if (mItemToAnimateInWhenWindowAnimationIsFinished != null) { + for (View v : + new View[] { holder.iconView, holder.labelView, holder.calloutLine }) { + if (v != null) { + v.setAlpha(1f); + v.setTranslationX(0f); + v.setTranslationY(0f); + } + } + } mItemToAnimateInWhenWindowAnimationIsFinished = holder; final int translation = -getResources().getDimensionPixelSize( R.dimen.status_bar_recents_app_icon_translate_distance); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index a857eba..248a516 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -35,7 +35,7 @@ public class NotificationPanelView extends PanelView { View mHandleView; int mFingers; PhoneStatusBar mStatusBar; - private boolean mFlipped; + boolean mOkToFlip; public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); @@ -94,10 +94,10 @@ public class NotificationPanelView extends PanelView { if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - mFlipped = false; + mOkToFlip = getExpandedHeight() == 0; break; case MotionEvent.ACTION_POINTER_DOWN: - if (!mFlipped) { + if (mOkToFlip) { float miny = event.getY(0); float maxy = miny; for (int i=1; i<event.getPointerCount(); i++) { @@ -111,7 +111,7 @@ public class NotificationPanelView extends PanelView { } else { mStatusBar.flipToSettings(); } - mFlipped = true; + mOkToFlip = false; } } break; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 91d5eaa..24ce9bc 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -299,6 +299,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mCarDockRotation; int mDeskDockRotation; int mHdmiRotation; + boolean mHdmiRotationLock; int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; int mUserRotation = Surface.ROTATION_0; @@ -1035,11 +1036,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { mCanHideNavigationBar = false; } + // For demo purposes, allow the rotation of the HDMI display to be controlled. + // By default, HDMI locks rotation to landscape. if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { mHdmiRotation = mPortraitRotation; } else { mHdmiRotation = mLandscapeRotation; } + mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", true); } public void updateSettings() { @@ -3873,7 +3877,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // enable 180 degree rotation while docked. preferredRotation = mDeskDockEnablesAccelerometer ? sensorRotation : mDeskDockRotation; - } else if (mHdmiPlugged) { + } else if (mHdmiPlugged && mHdmiRotationLock) { // Ignore sensor when plugged into HDMI. // Note that the dock orientation overrides the HDMI orientation. preferredRotation = mHdmiRotation; @@ -4538,5 +4542,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); + pw.print(prefix); pw.print("mHdmiRotation="); pw.print(mHdmiRotation); + pw.print(" mHdmiRotationLock="); pw.println(mHdmiRotationLock); } } 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 0ad2404..b66c883 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java @@ -43,7 +43,7 @@ import com.android.internal.widget.LockPatternUtils; /** * Manages creating, showing, hiding and resetting the keyguard. Calls back - * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke + * via {@link KeyguardViewMediator.ViewMediatorCallback} to poke * the wake lock and report that the keyguard is done, which is in turn, * reported to this class by the current {@link KeyguardViewBase}. */ @@ -233,6 +233,7 @@ public class KeyguardViewManager { if (mScreenOn) { mKeyguardView.show(); + mKeyguardView.requestFocus(); } } @@ -314,22 +315,25 @@ public class KeyguardViewManager { // Caller should wait for this window to be shown before turning // on the screen. - if (mKeyguardHost.getVisibility() == View.VISIBLE) { - // Keyguard may be in the process of being shown, but not yet - // updated with the window manager... give it a chance to do so. - mKeyguardHost.post(new Runnable() { - public void run() { - if (mKeyguardHost.getVisibility() == View.VISIBLE) { - showListener.onShown(mKeyguardHost.getWindowToken()); - } else { - showListener.onShown(null); + if (showListener != null) { + if (mKeyguardHost.getVisibility() == View.VISIBLE) { + // Keyguard may be in the process of being shown, but not yet + // updated with the window manager... give it a chance to do so. + mKeyguardHost.post(new Runnable() { + @Override + public void run() { + if (mKeyguardHost.getVisibility() == View.VISIBLE) { + showListener.onShown(mKeyguardHost.getWindowToken()); + } else { + showListener.onShown(null); + } } - } - }); - } else { - showListener.onShown(null); + }); + } else { + showListener.onShown(null); + } } - } else { + } else if (showListener != null) { showListener.onShown(null); } } @@ -356,10 +360,9 @@ public class KeyguardViewManager { if (mKeyguardView != null) { mKeyguardView.wakeWhenReadyTq(keyCode); return true; - } else { - Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq"); - return false; } + Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq"); + return false; } /** @@ -382,6 +385,7 @@ public class KeyguardViewManager { final KeyguardViewBase lastView = mKeyguardView; mKeyguardView = null; mKeyguardHost.postDelayed(new Runnable() { + @Override public void run() { synchronized (KeyguardViewManager.this) { lastView.cleanUp(); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java index 92f9dfd..ceb0325 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java @@ -629,9 +629,7 @@ public class KeyguardViewMediator { mScreenOn = true; cancelDoKeyguardLaterLocked(); if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence); - if (showListener != null) { - notifyScreenOnLocked(showListener); - } + notifyScreenOnLocked(showListener); } maybeSendUserPresentBroadcast(); } @@ -1365,7 +1363,7 @@ public class KeyguardViewMediator { /** * Handle message sent by {@link #verifyUnlock} - * @see #RESET + * @see #VERIFY_UNLOCK */ private void handleVerifyUnlock() { synchronized (KeyguardViewMediator.this) { diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java index b4dab86..e76bf44 100644 --- a/services/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/java/com/android/server/display/DisplayDeviceInfo.java @@ -17,6 +17,7 @@ package com.android.server.display; import android.util.DisplayMetrics; +import android.view.Surface; import libcore.util.Objects; @@ -31,11 +32,21 @@ final class DisplayDeviceInfo { public static final int FLAG_DEFAULT_DISPLAY = 1 << 0; /** - * Flag: Indicates that this display device can rotate to show contents in a - * different orientation. Otherwise the rotation is assumed to be fixed in the - * natural orientation and the display manager should transform the content to fit. + * Flag: Indicates that the orientation of this display device is coupled to the + * rotation of its associated logical display. + * <p> + * This flag should be applied to the default display to indicate that the user + * physically rotates the display when content is presented in a different orientation. + * The display manager will apply a coordinate transformation assuming that the + * physical orientation of the display matches the logical orientation of its content. + * </p><p> + * The flag should not be set when the display device is mounted in a fixed orientation + * such as on a desk. The display manager will apply a coordinate transformation + * such as a scale and translation to letterbox or pillarbox format under the + * assumption that the physical orientation of the display is invariant. + * </p> */ - public static final int FLAG_SUPPORTS_ROTATION = 1 << 1; + public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1; /** * Flag: Indicates that this display device has secure video output, such as HDCP. @@ -116,6 +127,17 @@ final class DisplayDeviceInfo { */ public int touch; + /** + * The additional rotation to apply to all content presented on the display device + * relative to its physical coordinate system. Default is {@link Surface#ROTATION_0}. + * <p> + * This field can be used to compensate for the fact that the display has been + * physically rotated relative to its natural orientation such as an HDMI monitor + * that has been mounted sideways to appear to be portrait rather than landscape. + * </p> + */ + public int rotation = Surface.ROTATION_0; + public void setAssumedDensityForExternalDisplay(int width, int height) { densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080; // Technically, these values should be smaller than the apparent density @@ -139,7 +161,8 @@ final class DisplayDeviceInfo { && xDpi == other.xDpi && yDpi == other.yDpi && flags == other.flags - && touch == other.touch; + && touch == other.touch + && rotation == other.rotation; } @Override @@ -157,14 +180,18 @@ final class DisplayDeviceInfo { yDpi = other.yDpi; flags = other.flags; touch = other.touch; + rotation = other.rotation; } // For debugging purposes @Override public String toString() { - return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, " + return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", " + + refreshRate + " fps, " + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi" - + ", touch " + touchToString(touch) + flagsToString(flags) + "}"; + + ", touch " + touchToString(touch) + flagsToString(flags) + + ", rotation " + rotation + + "}"; } private static String touchToString(int touch) { @@ -185,8 +212,8 @@ final class DisplayDeviceInfo { if ((flags & FLAG_DEFAULT_DISPLAY) != 0) { msg.append(", FLAG_DEFAULT_DISPLAY"); } - if ((flags & FLAG_SUPPORTS_ROTATION) != 0) { - msg.append(", FLAG_SUPPORTS_ROTATION"); + if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) { + msg.append(", FLAG_ROTATES_WITH_CONTENT"); } if ((flags & FLAG_SECURE) != 0) { msg.append(", FLAG_SECURE"); diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 93896af..e58a0a5 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -127,6 +127,13 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // services should be started. This option may disable certain display adapters. public boolean mOnlyCore; + // True if the display manager service should pretend there is only one display + // and only tell applications about the existence of the default logical display. + // The display manager can still mirror content to secondary displays but applications + // cannot present unique content on those displays. + // Used for demonstration purposes only. + private final boolean mSingleDisplayDemoMode; + // All callback records indexed by calling process id. public final SparseArray<CallbackRecord> mCallbacks = new SparseArray<CallbackRecord>(); @@ -182,6 +189,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { mHandler = new DisplayManagerHandler(mainHandler.getLooper()); mUiHandler = uiHandler; mDisplayAdapterListener = new DisplayAdapterListener(); + mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER); } @@ -631,6 +639,12 @@ public final class DisplayManagerService extends IDisplayManager.Stub { isDefault = false; } + if (!isDefault && mSingleDisplayDemoMode) { + Slog.i(TAG, "Not creating a logical display for a secondary display " + + " because single display demo mode is enabled: " + deviceInfo); + return; + } + final int displayId = assignDisplayIdLocked(isDefault); final int layerStack = assignLayerStackLocked(displayId); @@ -857,6 +871,7 @@ public final class DisplayManagerService extends IDisplayManager.Stub { pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId); pw.println(" mDefaultViewport=" + mDefaultViewport); pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); + pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); ipw.increaseIndent(); diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java index d780006..fe38d7f 100644 --- a/services/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/java/com/android/server/display/LocalDisplayAdapter.java @@ -20,6 +20,7 @@ import android.content.Context; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.SystemProperties; import android.util.SparseArray; import android.view.DisplayEventReceiver; import android.view.Surface; @@ -135,7 +136,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { mInfo.name = getContext().getResources().getString( com.android.internal.R.string.display_manager_built_in_display_name); mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY - | DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION; + | DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f); mInfo.xDpi = mPhys.xDpi; mInfo.yDpi = mPhys.yDpi; @@ -145,6 +146,12 @@ final class LocalDisplayAdapter extends DisplayAdapter { com.android.internal.R.string.display_manager_hdmi_display_name); mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height); + + // For demonstration purposes, allow rotation of the external display. + // In the future we might allow the user to configure this directly. + if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { + mInfo.rotation = Surface.ROTATION_270; + } } } return mInfo; diff --git a/services/java/com/android/server/display/LogicalDisplay.java b/services/java/com/android/server/display/LogicalDisplay.java index 680662e..aa7ea82 100644 --- a/services/java/com/android/server/display/LogicalDisplay.java +++ b/services/java/com/android/server/display/LogicalDisplay.java @@ -241,10 +241,13 @@ final class LogicalDisplay { // is rotated when the contents of the logical display are rendered. int orientation = Surface.ROTATION_0; if (device == mPrimaryDisplayDevice - && (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION) != 0) { + && (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) { orientation = displayInfo.rotation; } + // Apply the physical rotation of the display device itself. + orientation = (orientation + displayDeviceInfo.rotation) % 4; + // Set the frame. // The frame specifies the rotated physical coordinates into which the viewport // is mapped. We need to take care to preserve the aspect ratio of the viewport. diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index c441b02..66eac88 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -16,17 +16,28 @@ package com.android.server.display; +import com.android.internal.R; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; import android.hardware.display.DisplayManager; import android.hardware.display.WifiDisplay; import android.hardware.display.WifiDisplayStatus; import android.media.RemoteDisplay; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.UserHandle; +import android.provider.Settings; import android.util.Slog; import android.view.Surface; @@ -52,8 +63,18 @@ final class WifiDisplayAdapter extends DisplayAdapter { private static final boolean DEBUG = false; + private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1; + private static final int MSG_UPDATE_NOTIFICATION = 2; + + private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT"; + + private final WifiDisplayHandler mHandler; private final PersistentDataStore mPersistentDataStore; private final boolean mSupportsProtectedBuffers; + private final NotificationManager mNotificationManager; + + private final PendingIntent mSettingsPendingIntent; + private final PendingIntent mDisconnectPendingIntent; private WifiDisplayController mDisplayController; private WifiDisplayDevice mDisplayDevice; @@ -67,14 +88,32 @@ final class WifiDisplayAdapter extends DisplayAdapter { private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY; private boolean mPendingStatusChangeBroadcast; + private boolean mPendingNotificationUpdate; public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, Context context, Handler handler, Listener listener, PersistentDataStore persistentDataStore) { super(syncRoot, context, handler, listener, TAG); + mHandler = new WifiDisplayHandler(handler.getLooper()); mPersistentDataStore = persistentDataStore; mSupportsProtectedBuffers = context.getResources().getBoolean( com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers); + mNotificationManager = (NotificationManager)context.getSystemService( + Context.NOTIFICATION_SERVICE); + + Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS); + settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + mSettingsPendingIntent = PendingIntent.getActivityAsUser( + context, 0, settingsIntent, 0, null, UserHandle.CURRENT); + + Intent disconnectIntent = new Intent(ACTION_DISCONNECT); + mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser( + context, 0, disconnectIntent, 0, UserHandle.CURRENT); + + context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, + new IntentFilter(ACTION_DISCONNECT), null, mHandler); } @Override @@ -89,6 +128,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays)); pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays)); pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); + pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate); pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers); // Try to dump the controller state. @@ -266,6 +306,8 @@ final class WifiDisplayAdapter extends DisplayAdapter { mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, refreshRate, deviceFlags, surface); sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); + + scheduleUpdateNotificationLocked(); } private void handleDisconnectLocked() { @@ -273,6 +315,8 @@ final class WifiDisplayAdapter extends DisplayAdapter { mDisplayDevice.clearSurfaceLocked(); sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); mDisplayDevice = null; + + scheduleUpdateNotificationLocked(); } } @@ -280,28 +324,81 @@ final class WifiDisplayAdapter extends DisplayAdapter { mCurrentStatus = null; if (!mPendingStatusChangeBroadcast) { mPendingStatusChangeBroadcast = true; - getHandler().post(mStatusChangeBroadcast); + mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST); } } - private final Runnable mStatusChangeBroadcast = new Runnable() { - @Override - public void run() { - final Intent intent; - synchronized (getSyncRoot()) { - if (!mPendingStatusChangeBroadcast) { - return; - } + private void scheduleUpdateNotificationLocked() { + if (!mPendingNotificationUpdate) { + mPendingNotificationUpdate = true; + mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION); + } + } + + // Runs on the handler. + private void handleSendStatusChangeBroadcast() { + final Intent intent; + synchronized (getSyncRoot()) { + if (!mPendingStatusChangeBroadcast) { + return; + } + + mPendingStatusChangeBroadcast = false; + intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, + getWifiDisplayStatusLocked()); + } - mPendingStatusChangeBroadcast = false; - intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, - getWifiDisplayStatusLocked()); + // Send protected broadcast about wifi display status to registered receivers. + getContext().sendBroadcastAsUser(intent, UserHandle.ALL); + } + + // Runs on the handler. + private void handleUpdateNotification() { + final boolean isConnected; + synchronized (getSyncRoot()) { + if (!mPendingNotificationUpdate) { + return; } - // Send protected broadcast about wifi display status to registered receivers. - getContext().sendBroadcast(intent); + mPendingNotificationUpdate = false; + isConnected = (mDisplayDevice != null); + } + + mNotificationManager.cancelAsUser(null, + R.string.wifi_display_notification_title, UserHandle.ALL); + + if (isConnected) { + Context context = getContext(); + + Resources r = context.getResources(); + Notification notification = new Notification.Builder(context) + .setContentTitle(r.getString( + R.string.wifi_display_notification_title)) + .setContentText(r.getString( + R.string.wifi_display_notification_message)) + .setContentIntent(mSettingsPendingIntent) + .setSmallIcon(R.drawable.ic_notify_wifidisplay) + .setOngoing(true) + .addAction(android.R.drawable.ic_menu_close_clear_cancel, + r.getString(R.string.wifi_display_notification_disconnect), + mDisconnectPendingIntent) + .build(); + mNotificationManager.notifyAsUser(null, + R.string.wifi_display_notification_title, + notification, UserHandle.ALL); + } + } + + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(ACTION_DISCONNECT)) { + synchronized (getSyncRoot()) { + requestDisconnectLocked(); + } + } } }; @@ -454,4 +551,23 @@ final class WifiDisplayAdapter extends DisplayAdapter { return mInfo; } } + + private final class WifiDisplayHandler extends Handler { + public WifiDisplayHandler(Looper looper) { + super(looper, null, true /*async*/); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SEND_STATUS_CHANGE_BROADCAST: + handleSendStatusChangeBroadcast(); + break; + + case MSG_UPDATE_NOTIFICATION: + handleUpdateNotification(); + break; + } + } + } } diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index 4e692a2..b94bceb 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -107,6 +107,8 @@ public final class PowerManagerService extends IPowerManager.Stub private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9; // Dirty bit: screen on blocker state became held or unheld private static final int DIRTY_SCREEN_ON_BLOCKER_RELEASED = 1 << 10; + // Dirty bit: dock state changed + private static final int DIRTY_DOCK_STATE = 1 << 11; // Wakefulness: The device is asleep and can only be awoken by a call to wakeUp(). // The screen should be off or in the process of being turned off by the display controller. @@ -269,6 +271,9 @@ public final class PowerManagerService extends IPowerManager.Stub // draining faster than it is charging and the user activity timeout has expired. private int mBatteryLevelWhenDreamStarted; + // The current dock state. + private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; + // True if the device should wake up when plugged or unplugged. private boolean mWakeUpWhenPluggedOrUnpluggedConfig; @@ -281,6 +286,9 @@ public final class PowerManagerService extends IPowerManager.Stub // True if dreams should be activated on sleep. private boolean mDreamsActivateOnSleepSetting; + // True if dreams should be activated on dock. + private boolean mDreamsActivateOnDockSetting; + // The screen off timeout setting value in milliseconds. private int mScreenOffTimeoutSetting; @@ -440,6 +448,10 @@ public final class PowerManagerService extends IPowerManager.Stub filter.addAction(Intent.ACTION_USER_SWITCHED); mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler); + filter = new IntentFilter(); + filter.addAction(Intent.ACTION_DOCK_EVENT); + mContext.registerReceiver(new DockReceiver(), filter, null, mHandler); + // Register for settings changes. final ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.Secure.getUriFor( @@ -448,6 +460,9 @@ public final class PowerManagerService extends IPowerManager.Stub resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP), false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK), + false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_OFF_TIMEOUT), false, mSettingsObserver, UserHandle.USER_ALL); @@ -487,6 +502,9 @@ public final class PowerManagerService extends IPowerManager.Stub mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 0, UserHandle.USER_CURRENT) != 0); + mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver, + Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 0, + UserHandle.USER_CURRENT) != 0); mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver, Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT, UserHandle.USER_CURRENT); @@ -1339,13 +1357,14 @@ public final class PowerManagerService extends IPowerManager.Stub private boolean updateWakefulnessLocked(int dirty) { boolean changed = false; if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED - | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE)) != 0) { + | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE + | DIRTY_DOCK_STATE)) != 0) { if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) { if (DEBUG_SPEW) { Slog.d(TAG, "updateWakefulnessLocked: Bed time..."); } final long time = SystemClock.uptimeMillis(); - if (mDreamsActivateOnSleepSetting) { + if (shouldNapAtBedTimeLocked()) { changed = napNoUpdateLocked(time); } else { changed = goToSleepNoUpdateLocked(time, @@ -1357,6 +1376,16 @@ public final class PowerManagerService extends IPowerManager.Stub } /** + * Returns true if the device should automatically nap and start dreaming when the user + * activity timeout has expired and it's bedtime. + */ + private boolean shouldNapAtBedTimeLocked() { + return mDreamsActivateOnSleepSetting + || (mDreamsActivateOnDockSetting + && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED); + } + + /** * Returns true if the device should go to sleep now. * Also used when exiting a dream to determine whether we should go back * to being fully awake or else go to sleep for good. @@ -2124,6 +2153,7 @@ public final class PowerManagerService extends IPowerManager.Stub pw.println(" mPlugType=" + mPlugType); pw.println(" mBatteryLevel=" + mBatteryLevel); pw.println(" mBatteryLevelWhenDreamStarted=" + mBatteryLevelWhenDreamStarted); + pw.println(" mDockState=" + mDockState); pw.println(" mStayOn=" + mStayOn); pw.println(" mProximityPositive=" + mProximityPositive); pw.println(" mBootCompleted=" + mBootCompleted); @@ -2149,6 +2179,7 @@ public final class PowerManagerService extends IPowerManager.Stub pw.println(" mDreamsSupportedConfig=" + mDreamsSupportedConfig); pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting); pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting); + pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting); pw.println(" mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting); pw.println(" mMaximumScreenOffTimeoutFromDeviceAdmin=" + mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced=" @@ -2267,6 +2298,21 @@ public final class PowerManagerService extends IPowerManager.Stub } } + private final class DockReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + synchronized (mLock) { + int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, + Intent.EXTRA_DOCK_STATE_UNDOCKED); + if (mDockState != dockState) { + mDockState = dockState; + mDirty |= DIRTY_DOCK_STATE; + updatePowerStateLocked(); + } + } + } + } + private final class SettingsObserver extends ContentObserver { public SettingsObserver(Handler handler) { super(handler); diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png Binary files differnew file mode 100644 index 0000000..84e6bc8 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png Binary files differdeleted file mode 100644 index ac5a97b..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png Binary files differnew file mode 100644 index 0000000..38e4f45 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png Binary files differdeleted file mode 100644 index a90dc9b..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png Binary files differnew file mode 100644 index 0000000..bf9f300 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png Binary files differdeleted file mode 100644 index cb3c433..0000000 --- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png Binary files differnew file mode 100644 index 0000000..a00bc5b --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png Binary files differdeleted file mode 100644 index 5ab09f0..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png Binary files differnew file mode 100644 index 0000000..dc3183b --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png Binary files differdeleted file mode 100644 index 62ca427..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png Binary files differnew file mode 100644 index 0000000..b07f611 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png Binary files differdeleted file mode 100644 index ff698fb..0000000 --- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml index c5acddb..599ca08 100644 --- a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml @@ -1,5 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1"/> <ImageView android:layout_height="wrap_content" android:layout_width="wrap_content"/> @@ -13,12 +17,4 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1"/> - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content"/> - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_marginLeft="3dip" - android:layout_marginRight="15dip"/> </merge> diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml index d3c492e..d3c492e 100644 --- a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/status_bar.xml diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png Binary files differnew file mode 100644 index 0000000..bd60cd6 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png Binary files differdeleted file mode 100644 index 4cb305d..0000000 --- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png Binary files differnew file mode 100644 index 0000000..c5bc5c9 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png Binary files differdeleted file mode 100644 index 31d35c8..0000000 --- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png Binary files differnew file mode 100644 index 0000000..f621d9c --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png Binary files differdeleted file mode 100644 index f0cc341..0000000 --- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png +++ /dev/null diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index daf520b..bf8658e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -210,7 +210,8 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge { Capability.PLAY_ANIMATION, Capability.ANIMATED_VIEW_MANIPULATION, Capability.ADAPTER_BINDING, - Capability.EXTENDED_VIEWINFO); + Capability.EXTENDED_VIEWINFO, + Capability.FIXED_SCALABLE_NINE_PATCH); BridgeAssetManager.initSystem(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index 62c886b..ea9d8d9 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -60,11 +60,15 @@ abstract class CustomBar extends LinearLayout { protected abstract TextView getStyleableTextView(); - protected CustomBar(Context context, Density density, String layoutPath, String name) - throws XmlPullParserException { + protected CustomBar(Context context, Density density, int orientation, String layoutPath, + String name) throws XmlPullParserException { super(context); - setOrientation(LinearLayout.HORIZONTAL); - setGravity(Gravity.CENTER_VERTICAL); + setOrientation(orientation); + if (orientation == LinearLayout.HORIZONTAL) { + setGravity(Gravity.CENTER_VERTICAL); + } else { + setGravity(Gravity.CENTER_HORIZONTAL); + } LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java index 68f5aba..226649d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java @@ -21,6 +21,7 @@ import com.android.resources.Density; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; +import android.widget.LinearLayout; import android.widget.TextView; public class FakeActionBar extends CustomBar { @@ -29,7 +30,7 @@ public class FakeActionBar extends CustomBar { public FakeActionBar(Context context, Density density, String label, String icon) throws XmlPullParserException { - super(context, density, "/bars/action_bar.xml", "action_bar.xml"); + super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml"); // Cannot access the inside items through id because no R.id values have been // created for them. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java index 456ddb4..cc90d6b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java @@ -17,34 +17,34 @@ package com.android.layoutlib.bridge.bars; import com.android.resources.Density; -import com.android.resources.ResourceType; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LevelListDrawable; +import android.widget.LinearLayout; import android.widget.TextView; -public class TabletSystemBar extends CustomBar { +public class NavigationBar extends CustomBar { - public TabletSystemBar(Context context, Density density) throws XmlPullParserException { - super(context, density, "/bars/tablet_system_bar.xml", "tablet_system_bar.xml"); + public NavigationBar(Context context, Density density, int orientation) throws XmlPullParserException { + super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml"); setBackgroundColor(0xFF000000); // Cannot access the inside items through id because no R.id values have been // created for them. // We do know the order though. - loadIcon(0, "ic_sysbar_back_default.png", density); - loadIcon(1, "ic_sysbar_home_default.png", density); - loadIcon(2, "ic_sysbar_recent_default.png", density); - // 3 is the spacer - loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density); - Drawable drawable = loadIcon(5, ResourceType.DRAWABLE, "stat_sys_battery_charge"); - if (drawable instanceof LevelListDrawable) { - ((LevelListDrawable) drawable).setLevel(100); + // 0 is a spacer. + int back = 1; + int recent = 3; + if (orientation == LinearLayout.VERTICAL) { + back = 3; + recent = 1; } + + loadIcon(back, "ic_sysbar_back.png", density); + loadIcon(2, "ic_sysbar_home.png", density); + loadIcon(recent, "ic_sysbar_recent.png", density); } @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java index 7521011..5c08412 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java @@ -25,12 +25,13 @@ import android.content.Context; import android.graphics.drawable.Drawable; import android.graphics.drawable.LevelListDrawable; import android.view.Gravity; +import android.widget.LinearLayout; import android.widget.TextView; -public class PhoneSystemBar extends CustomBar { +public class StatusBar extends CustomBar { - public PhoneSystemBar(Context context, Density density) throws XmlPullParserException { - super(context, density, "/bars/phone_system_bar.xml", "phone_system_bar.xml"); + public StatusBar(Context context, Density density) throws XmlPullParserException { + super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml"); // FIXME: use FILL_H? setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java index 5f5ebc4..c27859f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java @@ -21,6 +21,7 @@ import com.android.resources.Density; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; +import android.widget.LinearLayout; import android.widget.TextView; public class TitleBar extends CustomBar { @@ -29,7 +30,7 @@ public class TitleBar extends CustomBar { public TitleBar(Context context, Density density, String label) throws XmlPullParserException { - super(context, density, "/bars/title_bar.xml", "title_bar.xml"); + super(context, density, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml"); // Cannot access the inside items through id because no R.id values have been // created for them. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java index de65fd4..f109e39 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java @@ -20,11 +20,12 @@ import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTE import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT; import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; +import com.android.ide.common.rendering.api.HardwareConfig; import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.RenderParams; import com.android.ide.common.rendering.api.RenderResources; -import com.android.ide.common.rendering.api.Result; import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider; +import com.android.ide.common.rendering.api.Result; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.resources.Density; @@ -98,19 +99,22 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso return result; } + HardwareConfig hardwareConfig = mParams.getHardwareConfig(); + // setup the display Metrics. DisplayMetrics metrics = new DisplayMetrics(); - metrics.densityDpi = metrics.noncompatDensityDpi = mParams.getDensity().getDpiValue(); + metrics.densityDpi = metrics.noncompatDensityDpi = + hardwareConfig.getDensity().getDpiValue(); metrics.density = metrics.noncompatDensity = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT; metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density; - metrics.widthPixels = metrics.noncompatWidthPixels = mParams.getScreenWidth(); - metrics.heightPixels = metrics.noncompatHeightPixels = mParams.getScreenHeight(); - metrics.xdpi = metrics.noncompatXdpi = mParams.getXdpi(); - metrics.ydpi = metrics.noncompatYdpi = mParams.getYdpi(); + metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth(); + metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight(); + metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi(); + metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi(); RenderResources resources = mParams.getResources(); @@ -305,7 +309,9 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso private Configuration getConfiguration() { Configuration config = new Configuration(); - ScreenSize screenSize = mParams.getConfigScreenSize(); + HardwareConfig hardwareConfig = mParams.getHardwareConfig(); + + ScreenSize screenSize = hardwareConfig.getScreenSize(); if (screenSize != null) { switch (screenSize) { case SMALL: @@ -323,13 +329,13 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso } } - Density density = mParams.getDensity(); + Density density = hardwareConfig.getDensity(); if (density == null) { density = Density.MEDIUM; } - config.screenWidthDp = mParams.getScreenWidth() / density.getDpiValue(); - config.screenHeightDp = mParams.getScreenHeight() / density.getDpiValue(); + config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue(); + config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue(); if (config.screenHeightDp < config.screenWidthDp) { config.smallestScreenWidthDp = config.screenHeightDp; } else { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java index 8133210..b677131 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java @@ -19,6 +19,7 @@ package com.android.layoutlib.bridge.impl; import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; import com.android.ide.common.rendering.api.DrawableParams; +import com.android.ide.common.rendering.api.HardwareConfig; import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.Result; import com.android.ide.common.rendering.api.Result.Status; @@ -59,6 +60,7 @@ public class RenderDrawable extends RenderAction<DrawableParams> { try { // get the drawable resource value DrawableParams params = getParams(); + HardwareConfig hardwareConfig = params.getHardwareConfig(); ResourceValue drawableResource = params.getDrawable(); // resolve it @@ -75,15 +77,15 @@ public class RenderDrawable extends RenderAction<DrawableParams> { // get the actual Drawable object to draw Drawable d = ResourceHelper.getDrawable(drawableResource, context); - content.setBackgroundDrawable(d); + content.setBackground(d); // set the AttachInfo on the root view. AttachInfo_Accessor.setAttachInfo(content); // measure - int w = params.getScreenWidth(); - int h = params.getScreenHeight(); + int w = hardwareConfig.getScreenWidth(); + int h = hardwareConfig.getScreenHeight(); int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); content.measure(w_spec, h_spec); @@ -99,11 +101,11 @@ public class RenderDrawable extends RenderAction<DrawableParams> { // create an Android bitmap around the BufferedImage Bitmap bitmap = Bitmap_Delegate.createBitmap(image, - true /*isMutable*/, params.getDensity()); + true /*isMutable*/, hardwareConfig.getDensity()); // create a Canvas around the Android bitmap Canvas canvas = new Canvas(bitmap); - canvas.setDensity(params.getDensity().getDpiValue()); + canvas.setDensity(hardwareConfig.getDensity().getDpiValue()); // and draw content.draw(canvas); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index cc0f077..c14af4a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -24,6 +24,7 @@ import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP import static com.android.ide.common.rendering.api.Result.Status.SUCCESS; import com.android.ide.common.rendering.api.AdapterBinding; +import com.android.ide.common.rendering.api.HardwareConfig; import com.android.ide.common.rendering.api.IAnimationListener; import com.android.ide.common.rendering.api.ILayoutPullParser; import com.android.ide.common.rendering.api.IProjectCallback; @@ -43,13 +44,13 @@ import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; import com.android.layoutlib.bridge.bars.FakeActionBar; -import com.android.layoutlib.bridge.bars.PhoneSystemBar; -import com.android.layoutlib.bridge.bars.TabletSystemBar; +import com.android.layoutlib.bridge.bars.NavigationBar; +import com.android.layoutlib.bridge.bars.StatusBar; import com.android.layoutlib.bridge.bars.TitleBar; import com.android.layoutlib.bridge.impl.binding.FakeAdapter; import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; import com.android.resources.ResourceType; -import com.android.resources.ScreenSize; +import com.android.resources.ScreenOrientation; import com.android.util.Pair; import org.xmlpull.v1.XmlPullParserException; @@ -68,8 +69,8 @@ import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.AttachInfo_Accessor; import android.view.BridgeInflater; -import android.view.IWindowManagerImpl; import android.view.IWindowManager; +import android.view.IWindowManagerImpl; import android.view.Surface; import android.view.View; import android.view.View.MeasureSpec; @@ -124,7 +125,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { private boolean mWindowIsFloating; private int mStatusBarSize; - private int mSystemBarSize; + private int mNavigationBarSize; + private int mNavigationBarOrientation = LinearLayout.HORIZONTAL; private int mTitleBarSize; private int mActionBarSize; @@ -187,7 +189,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { findBackground(resources); findStatusBar(resources, metrics); findActionBar(resources, metrics); - findSystemBar(resources, metrics); + findNavigationBar(resources, metrics); // FIXME: find those out, and possibly add them to the render params boolean hasSystemNavBar = true; @@ -221,19 +223,57 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { try { SessionParams params = getParams(); + HardwareConfig hardwareConfig = params.getHardwareConfig(); BridgeContext context = getContext(); + // the view group that receives the window background. ViewGroup backgroundView = null; if (mWindowIsFloating || params.isForceNoDecor()) { backgroundView = mViewRoot = mContentRoot = new FrameLayout(context); } else { + if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) { + /* + * This is a special case where the navigation bar is on the right. + +-------------------------------------------------+---+ + | Status bar (always) | | + +-------------------------------------------------+ | + | (Layout with background drawable) | | + | +---------------------------------------------+ | | + | | Title/Action bar (optional) | | | + | +---------------------------------------------+ | | + | | Content, vertical extending | | | + | | | | | + | +---------------------------------------------+ | | + +-------------------------------------------------+---+ + + So we create a horizontal layout, with the nav bar on the right, + and the left part is the normal layout below without the nav bar at + the bottom + */ + LinearLayout topLayout = new LinearLayout(context); + mViewRoot = topLayout; + topLayout.setOrientation(LinearLayout.HORIZONTAL); + + try { + NavigationBar navigationBar = new NavigationBar(context, + hardwareConfig.getDensity(), LinearLayout.VERTICAL); + navigationBar.setLayoutParams( + new LinearLayout.LayoutParams( + mNavigationBarSize, + LayoutParams.MATCH_PARENT)); + topLayout.addView(navigationBar); + } catch (XmlPullParserException e) { + + } + } + /* * we're creating the following layout * +-------------------------------------------------+ - | System bar (only in phone UI) | + | Status bar (always) | +-------------------------------------------------+ | (Layout with background drawable) | | +---------------------------------------------+ | @@ -243,20 +283,31 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { | | | | | +---------------------------------------------+ | +-------------------------------------------------+ - | System bar (only in tablet UI) | + | Navigation bar for soft buttons, maybe see above| +-------------------------------------------------+ */ LinearLayout topLayout = new LinearLayout(context); - mViewRoot = topLayout; topLayout.setOrientation(LinearLayout.VERTICAL); + // if we don't already have a view root this is it + if (mViewRoot == null) { + mViewRoot = topLayout; + } else { + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + layoutParams.weight = 1; + topLayout.setLayoutParams(layoutParams); + + // this is the case of soft buttons + vertical bar. + // this top layout is the first layout in the horizontal layout. see above) + mViewRoot.addView(topLayout, 0); + } if (mStatusBarSize > 0) { // system bar try { - PhoneSystemBar systemBar = new PhoneSystemBar(context, - params.getDensity()); + StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity()); systemBar.setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, mStatusBarSize)); @@ -280,7 +331,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { if (mActionBarSize > 0) { try { FakeActionBar actionBar = new FakeActionBar(context, - params.getDensity(), + hardwareConfig.getDensity(), params.getAppLabel(), params.getAppIcon()); actionBar.setLayoutParams( new LinearLayout.LayoutParams( @@ -292,7 +343,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } else if (mTitleBarSize > 0) { try { TitleBar titleBar = new TitleBar(context, - params.getDensity(), params.getAppLabel()); + hardwareConfig.getDensity(), params.getAppLabel()); titleBar.setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, mTitleBarSize)); @@ -310,15 +361,16 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { mContentRoot.setLayoutParams(layoutParams); backgroundLayout.addView(mContentRoot); - if (mSystemBarSize > 0) { + if (mNavigationBarOrientation == LinearLayout.HORIZONTAL && + mNavigationBarSize > 0) { // system bar try { - TabletSystemBar systemBar = new TabletSystemBar(context, - params.getDensity()); - systemBar.setLayoutParams( + NavigationBar navigationBar = new NavigationBar(context, + hardwareConfig.getDensity(), LinearLayout.HORIZONTAL); + navigationBar.setLayoutParams( new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, mSystemBarSize)); - topLayout.addView(systemBar); + LayoutParams.MATCH_PARENT, mNavigationBarSize)); + topLayout.addView(navigationBar); } catch (XmlPullParserException e) { } @@ -346,7 +398,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { // get the background drawable if (mWindowBackground != null && backgroundView != null) { Drawable d = ResourceHelper.getDrawable(mWindowBackground, context); - backgroundView.setBackgroundDrawable(d); + backgroundView.setBackground(d); } return SUCCESS.createResult(); @@ -389,13 +441,14 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } RenderingMode renderingMode = params.getRenderingMode(); + HardwareConfig hardwareConfig = params.getHardwareConfig(); // only do the screen measure when needed. boolean newRenderSize = false; if (mMeasuredScreenWidth == -1) { newRenderSize = true; - mMeasuredScreenWidth = params.getScreenWidth(); - mMeasuredScreenHeight = params.getScreenHeight(); + mMeasuredScreenWidth = hardwareConfig.getScreenWidth(); + mMeasuredScreenHeight = hardwareConfig.getScreenHeight(); if (renderingMode != RenderingMode.NORMAL) { int widthMeasureSpecMode = renderingMode.isHorizExpand() ? @@ -495,11 +548,11 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { // create an Android bitmap around the BufferedImage Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, - true /*isMutable*/, params.getDensity()); + true /*isMutable*/, hardwareConfig.getDensity()); // create a Canvas around the Android bitmap mCanvas = new Canvas(bitmap); - mCanvas.setDensity(params.getDensity().getDpiValue()); + mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); } if (freshRender && newImage == false) { @@ -972,30 +1025,28 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } } - private boolean isTabletUi() { - return getParams().getConfigScreenSize() == ScreenSize.XLARGE; + private boolean hasSoftwareButtons() { + return getParams().getHardwareConfig().hasSoftwareButtons(); } private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { - if (isTabletUi() == false) { - boolean windowFullscreen = getBooleanThemeValue(resources, - "windowFullscreen", false /*defaultValue*/); + boolean windowFullscreen = getBooleanThemeValue(resources, + "windowFullscreen", false /*defaultValue*/); - if (windowFullscreen == false && mWindowIsFloating == false) { - // default value - mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; + if (windowFullscreen == false && mWindowIsFloating == false) { + // default value + mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; - // get the real value - ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, - "status_bar_height"); + // get the real value + ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, + "status_bar_height"); - if (value != null) { - TypedValue typedValue = ResourceHelper.getValue("status_bar_height", - value.getValue(), true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mStatusBarSize = (int)typedValue.getDimension(metrics); - } + if (value != null) { + TypedValue typedValue = ResourceHelper.getValue("status_bar_height", + value.getValue(), true /*requireUnit*/); + if (typedValue != null) { + // compute the pixel value based on the display metrics + mStatusBarSize = (int)typedValue.getDimension(metrics); } } } @@ -1062,22 +1113,48 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } } - private void findSystemBar(RenderResources resources, DisplayMetrics metrics) { - if (isTabletUi() && mWindowIsFloating == false) { + private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) { + if (hasSoftwareButtons() && mWindowIsFloating == false) { // default value - mSystemBarSize = 48; // ?? + mNavigationBarSize = 48; // ?? + + HardwareConfig hardwareConfig = getParams().getHardwareConfig(); + + boolean barOnBottom = true; + + if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) { + // compute the dp of the screen. + int shortSize = hardwareConfig.getScreenHeight(); + + // compute in dp + int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue(); + + if (shortSizeDp < 600) { + // 0-599dp: "phone" UI with bar on the side + barOnBottom = false; + } else { + // 600+dp: "tablet" UI with bar on the bottom + barOnBottom = true; + } + } + + if (barOnBottom) { + mNavigationBarOrientation = LinearLayout.HORIZONTAL; + } else { + mNavigationBarOrientation = LinearLayout.VERTICAL; + } // get the real value ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, - "status_bar_height"); + barOnBottom ? "navigation_bar_height" : "navigation_bar_width"); if (value != null) { - TypedValue typedValue = ResourceHelper.getValue("status_bar_height", + TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height", value.getValue(), true /*requireUnit*/); if (typedValue != null) { // compute the pixel value based on the display metrics - mSystemBarSize = (int)typedValue.getDimension(metrics); + mNavigationBarSize = (int)typedValue.getDimension(metrics); } } } diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java index 9c727f9..c8f0712 100644 --- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java +++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java @@ -556,8 +556,8 @@ public class WifiWatchdogStateMachine extends StateMachine { mLinkProperties = (LinkProperties) intent.getParcelableExtra( WifiManager.EXTRA_LINK_PROPERTIES); if (mPoorNetworkDetectionEnabled) { - if (mWifiInfo == null) { - if (DBG) logd("Ignoring link verification, mWifiInfo is NULL"); + if (mWifiInfo == null || mCurrentBssid == null) { + loge("Ignore, wifiinfo " + mWifiInfo +" bssid " + mCurrentBssid); sendLinkStatusNotification(true); } else { transitionTo(mVerifyingLinkState); @@ -726,7 +726,7 @@ public class WifiWatchdogStateMachine extends StateMachine { } private void handleRssiChange() { - if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD) { + if (mCurrentSignalLevel <= LINK_MONITOR_LEVEL_THRESHOLD && mCurrentBssid != null) { transitionTo(mLinkMonitoringState); } else { // stay here @@ -920,11 +920,15 @@ public class WifiWatchdogStateMachine extends StateMachine { if (DBG) logd("########################################"); if (isGood) { mWsmChannel.sendMessage(GOOD_LINK_DETECTED); - mCurrentBssid.mLastTimeGood = SystemClock.elapsedRealtime(); - logd("Good link notification is sent"); + if (mCurrentBssid != null) { + mCurrentBssid.mLastTimeGood = SystemClock.elapsedRealtime(); + } + if (DBG) logd("Good link notification is sent"); } else { mWsmChannel.sendMessage(POOR_LINK_DETECTED); - mCurrentBssid.mLastTimePoor = SystemClock.elapsedRealtime(); + if (mCurrentBssid != null) { + mCurrentBssid.mLastTimePoor = SystemClock.elapsedRealtime(); + } logd("Poor link notification is sent"); } } |