diff options
85 files changed, 1215 insertions, 420 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 16d4ad6..42c9d34 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -1131,6 +1131,19 @@ public final class Pm { } private void runClear() { + int userId = 0; + String option = nextOption(); + if (option != null && option.equals("--user")) { + String optionData = nextOptionData(); + if (optionData == null || !isNumber(optionData)) { + System.err.println("Error: no USER_ID specified"); + showUsage(); + return; + } else { + userId = Integer.parseInt(optionData); + } + } + String pkg = nextArg(); if (pkg == null) { System.err.println("Error: no package specified"); @@ -1140,8 +1153,7 @@ public final class Pm { ClearDataObserver obs = new ClearDataObserver(); try { - // XXX TO DO: add user arg - if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, 0)) { + if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId)) { System.err.println("Failed"); } @@ -1179,7 +1191,7 @@ public final class Pm { return "unknown"; } - private boolean isNumber(String s) { + private static boolean isNumber(String s) { try { Integer.parseInt(s); } catch (NumberFormatException nfe) { @@ -1452,7 +1464,7 @@ public final class Pm { System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]"); System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); - System.err.println(" pm clear PACKAGE"); + System.err.println(" pm clear [--user USER_ID] PACKAGE"); System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT"); System.err.println(" pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT"); diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index de4dd88..affeb90 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -283,6 +283,8 @@ public class SearchManagerService extends ISearchManager.Stub { @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); + IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); synchronized (mSearchables) { for (int i = 0; i < mSearchables.size(); i++) { diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index c72b714..4820c5e 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -612,18 +612,23 @@ public class DreamService extends Service implements Window.Callback { View.SYSTEM_UI_FLAG_LOW_PROFILE); getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); } catch (Throwable t) { - Slog.w("Crashed adding window view", t); + Slog.w(TAG, "Crashed adding window view", t); safelyFinish(); return; } // start it up - try { - onDreamingStarted(); - } catch (Throwable t) { - Slog.w("Crashed in onDreamingStarted()", t); - safelyFinish(); - } + mHandler.post(new Runnable() { + @Override + public void run() { + try { + onDreamingStarted(); + } catch (Throwable t) { + Slog.w(TAG, "Crashed in onDreamingStarted()", t); + safelyFinish(); + } + } + }); } private void safelyFinish() { diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 37e0a36..ec1695e 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -925,8 +925,17 @@ public abstract class HardwareRenderer { sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value); Log.d(LOG_TAG, " STENCIL_SIZE = " + value[0]); + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLE_BUFFERS, value); + Log.d(LOG_TAG, " SAMPLE_BUFFERS = " + value[0]); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLES, value); + Log.d(LOG_TAG, " SAMPLES = " + value[0]); + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value); Log.d(LOG_TAG, " SURFACE_TYPE = 0x" + Integer.toHexString(value[0])); + + sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_CONFIG_CAVEAT, value); + Log.d(LOG_TAG, " CONFIG_CAVEAT = 0x" + Integer.toHexString(value[0])); } GL createEglSurface(Surface surface) throws Surface.OutOfResourcesException { @@ -1433,6 +1442,7 @@ public abstract class HardwareRenderer { EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, + EGL_CONFIG_CAVEAT, EGL_NONE, // TODO: Find a better way to choose the stencil size EGL_STENCIL_SIZE, mShowOverdraw ? GLES20Canvas.getStencilSize() : 0, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 07bb8f9..7ef6939 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -245,6 +245,7 @@ public class Surface implements Parcelable { private static native void nativeOpenTransaction(); private static native void nativeCloseTransaction(); + private static native void nativeSetAnimationTransaction(); private native void nativeSetLayer(int zorder); private native void nativeSetPosition(float x, float y); @@ -525,6 +526,11 @@ public class Surface implements Parcelable { nativeCloseTransaction(); } + /** flag the transaction as an animation @hide */ + public static void setAnimationTransaction() { + nativeSetAnimationTransaction(); + } + /** @hide */ public void setLayer(int zorder) { nativeSetLayer(zorder); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 946965b..158e0c0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10515,9 +10515,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <p>Causes the Runnable to be added to the message queue. * The runnable will be run on the user interface thread.</p> * - * <p>This method can be invoked from outside of the UI thread - * only when this View is attached to a window.</p> - * * @param action The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the @@ -10542,9 +10539,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * after the specified amount of time elapses. * The runnable will be run on the user interface thread.</p> * - * <p>This method can be invoked from outside of the UI thread - * only when this View is attached to a window.</p> - * * @param action The Runnable that will be executed. * @param delayMillis The delay (in milliseconds) until the Runnable * will be executed. @@ -10573,9 +10567,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <p>Causes the Runnable to execute on the next animation time step. * The runnable will be run on the user interface thread.</p> * - * <p>This method can be invoked from outside of the UI thread - * only when this View is attached to a window.</p> - * * @param action The Runnable that will be executed. * * @see #postOnAnimationDelayed @@ -10597,9 +10588,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * after the specified amount of time elapses. * The runnable will be run on the user interface thread.</p> * - * <p>This method can be invoked from outside of the UI thread - * only when this View is attached to a window.</p> - * * @param action The Runnable that will be executed. * @param delayMillis The delay (in milliseconds) until the Runnable * will be executed. @@ -10621,9 +10609,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * <p>Removes the specified Runnable from the message queue.</p> * - * <p>This method can be invoked from outside of the UI thread - * only when this View is attached to a window.</p> - * * @param action The Runnable to remove from the message handling queue * * @return true if this view could ask the Handler to remove the Runnable, diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index b3c679c..751ed7c 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -367,6 +367,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mSingleLine; private int mDesiredHeightAtMeasure = -1; private boolean mIncludePad = true; + private int mDeferScroll = -1; // tmp primitives, so we don't alloc them on each draw private Rect mTempRect; @@ -6317,6 +6318,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); + if (mDeferScroll >= 0) { + int curs = mDeferScroll; + mDeferScroll = -1; + bringPointIntoView(curs); + } if (changed && mEditor != null) mEditor.invalidateTextDisplayList(); } @@ -6399,6 +6405,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * This has to be called after layout. Returns true if anything changed. */ public boolean bringPointIntoView(int offset) { + if (isLayoutRequested()) { + mDeferScroll = offset; + return false; + } boolean changed = false; Layout layout = isShowingHint() ? mHintLayout: mLayout; @@ -7108,13 +7118,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener registerForPreDraw(); } + checkForResize(); + if (curs >= 0) { mHighlightPathBogus = true; if (mEditor != null) mEditor.makeBlink(); bringPointIntoView(curs); } - - checkForResize(); } /** @@ -7161,6 +7171,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (oldStart >= 0 || newStart >= 0) { invalidateCursor(Selection.getSelectionStart(buf), oldStart, newStart); + checkForResize(); registerForPreDraw(); if (mEditor != null) mEditor.makeBlink(); } diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 4982f31..531445f 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -526,6 +526,10 @@ static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { SurfaceComposerClient::closeGlobalTransaction(); } +static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::setAnimationTransaction(); +} + static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint zorder) { sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); if (surface == NULL) return; @@ -819,6 +823,8 @@ static JNINativeMethod gSurfaceMethods[] = { (void*)nativeOpenTransaction }, {"nativeCloseTransaction", "()V", (void*)nativeCloseTransaction }, + {"nativeSetAnimationTransaction", "()V", + (void*)nativeSetAnimationTransaction }, {"nativeSetLayer", "(I)V", (void*)nativeSetLayer }, {"nativeSetPosition", "(FF)V", diff --git a/core/res/res/layout-land/keyguard_status_area.xml b/core/res/res/layout-land/keyguard_status_area.xml index 78bf931..f562d9f 100644 --- a/core/res/res/layout-land/keyguard_status_area.xml +++ b/core/res/res/layout-land/keyguard_status_area.xml @@ -41,6 +41,8 @@ <TextView android:id="@+id/alarm_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="end" android:layout_marginTop="28dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" @@ -53,6 +55,8 @@ <TextView android:id="@+id/owner_info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="end" android:layout_marginTop="4dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" @@ -64,6 +68,8 @@ <TextView android:id="@+id/status1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="end" android:layout_marginTop="4dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" @@ -75,6 +81,8 @@ <TextView android:id="@+id/status_security_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="right" android:layout_marginTop="12dp" diff --git a/core/res/res/layout-port/keyguard_host_view.xml b/core/res/res/layout-port/keyguard_host_view.xml index 3ce9365..20726d0 100644 --- a/core/res/res/layout-port/keyguard_host_view.xml +++ b/core/res/res/layout-port/keyguard_host_view.xml @@ -29,15 +29,14 @@ <include layout="@layout/keyguard_widget_region" android:layout_width="match_parent" - android:layout_height="0dip" - android:layout_weight="27" /> + android:layout_height="153dp" /> <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper android:id="@+id/view_flipper" android:layout_height="0dp" android:clipChildren="false" android:clipToPadding="false" - android:layout_weight="73" + android:layout_weight="1" android:paddingLeft="@dimen/keyguard_security_view_margin" android:paddingTop="@dimen/keyguard_security_view_margin" android:paddingRight="@dimen/keyguard_security_view_margin" diff --git a/core/res/res/layout-port/keyguard_status_area.xml b/core/res/res/layout-port/keyguard_status_area.xml index 00aac7b..e0a49dc 100644 --- a/core/res/res/layout-port/keyguard_status_area.xml +++ b/core/res/res/layout-port/keyguard_status_area.xml @@ -56,6 +56,8 @@ <TextView android:id="@+id/owner_info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="right" android:layout_marginTop="4dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" @@ -67,6 +69,8 @@ <TextView android:id="@+id/status1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="right" android:layout_marginTop="4dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" @@ -78,6 +82,8 @@ <TextView android:id="@+id/status_security_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="right" android:layout_marginTop="4dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" diff --git a/core/res/res/layout-sw600dp-port/keyguard_status_area.xml b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml index 679aebd..f21254a 100644 --- a/core/res/res/layout-sw600dp-port/keyguard_status_area.xml +++ b/core/res/res/layout-sw600dp-port/keyguard_status_area.xml @@ -41,6 +41,8 @@ <TextView android:id="@+id/alarm_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="end" android:layout_marginTop="28dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" @@ -53,6 +55,8 @@ <TextView android:id="@+id/owner_info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="end" android:layout_marginTop="4dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" @@ -64,6 +68,8 @@ <TextView android:id="@+id/status1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="end" android:layout_marginTop="4dp" android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml index 4f94f96..47d4728 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml @@ -89,7 +89,6 @@ android:layout_weight="1" android:gravity="center" android:layout_gravity="center" - android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left" android:singleLine="true" android:textStyle="normal" android:inputType="textPassword" diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml index 9a649fbb..6dd85cb 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml @@ -93,7 +93,6 @@ android:inputType="textPassword" android:gravity="center" android:layout_gravity="center" - android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left" android:textSize="24sp" android:textAppearance="?android:attr/textAppearanceMedium" android:background="@null" diff --git a/core/res/res/layout/keyguard_account_view.xml b/core/res/res/layout/keyguard_account_view.xml index 481f0c1..d1f9225 100644 --- a/core/res/res/layout/keyguard_account_view.xml +++ b/core/res/res/layout/keyguard_account_view.xml @@ -23,7 +23,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - <include layout="@layout/keyguard_navigation"/> + <include layout="@layout/keyguard_sim_puk_pin_account_navigation"/> <RelativeLayout android:layout_width="match_parent" @@ -69,4 +69,12 @@ </RelativeLayout> + <include layout="@layout/keyguard_emergency_carrier_area" + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_gravity="bottom|center_horizontal" + android:gravity="center_horizontal" /> + </com.android.internal.policy.impl.keyguard.KeyguardAccountView> diff --git a/core/res/res/layout/keyguard_emergency_carrier_area_and_recovery.xml b/core/res/res/layout/keyguard_emergency_carrier_area_and_recovery.xml new file mode 100644 index 0000000..68840ab --- /dev/null +++ b/core/res/res/layout/keyguard_emergency_carrier_area_and_recovery.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License") +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<!-- This contains emergency call button and carrier as shared by pin/pattern/password screens --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="center" + android:layout_gravity="center_horizontal" + android:layout_alignParentBottom="true"> + + <com.android.internal.policy.impl.keyguard.CarrierText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textSize="@dimen/kg_status_line_font_size" + android:textColor="?android:attr/textColorSecondary"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="?android:attr/buttonBarStyle" + android:orientation="horizontal" + android:gravity="center" + android:weightSum="2"> + + <com.android.internal.policy.impl.keyguard.EmergencyButton + android:id="@+id/emergency_call_button" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableLeft="@*android:drawable/lockscreen_emergency_button" + android:text="@string/kg_emergency_call_label" + style="?android:attr/buttonBarButtonStyle" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textSize="@dimen/kg_status_line_font_size" + android:textColor="?android:attr/textColorSecondary" + android:drawablePadding="8dip" /> + + <Button android:id="@+id/forgot_password_button" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:drawableLeft="@drawable/lockscreen_forgot_password_button" + style="?android:attr/buttonBarButtonStyle" + android:textSize="@dimen/kg_status_line_font_size" + android:textColor="?android:attr/textColorSecondary" + android:textAppearance="?android:attr/textAppearanceMedium" + android:drawablePadding="8dip" + android:visibility="gone"/> + </LinearLayout> + +</LinearLayout> diff --git a/core/res/res/layout/keyguard_glow_pad_container.xml b/core/res/res/layout/keyguard_glow_pad_container.xml index 9f3d394..376d0e9 100644 --- a/core/res/res/layout/keyguard_glow_pad_container.xml +++ b/core/res/res/layout/keyguard_glow_pad_container.xml @@ -22,5 +22,5 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|center_horizontal" - android:layout_marginBottom="-96dp"/> + android:layout_marginBottom="-80dp"/> </merge>
\ No newline at end of file diff --git a/core/res/res/layout/keyguard_password_view.xml b/core/res/res/layout/keyguard_password_view.xml index 92a7551..ab8aa85 100644 --- a/core/res/res/layout/keyguard_password_view.xml +++ b/core/res/res/layout/keyguard_password_view.xml @@ -26,11 +26,12 @@ <FrameLayout android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="0dp" + android:layout_weight="1"> <LinearLayout android:layout_height="wrap_content" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:orientation="vertical" android:layout_gravity="center"> @@ -114,14 +115,14 @@ android:clickable="true" /> </LinearLayout> - - <include layout="@layout/keyguard_emergency_carrier_area" - android:id="@+id/keyguard_selector_fade_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_gravity="bottom|center_horizontal" - android:gravity="center_horizontal" /> </LinearLayout> </FrameLayout> + <include layout="@layout/keyguard_emergency_carrier_area" + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_gravity="bottom|center_horizontal" + android:gravity="center_horizontal" /> + </com.android.internal.policy.impl.keyguard.KeyguardPasswordView> diff --git a/core/res/res/layout/keyguard_pattern_view.xml b/core/res/res/layout/keyguard_pattern_view.xml index 47dea9f..bec03b4 100644 --- a/core/res/res/layout/keyguard_pattern_view.xml +++ b/core/res/res/layout/keyguard_pattern_view.xml @@ -38,21 +38,7 @@ android:orientation="vertical" android:layout_gravity="center"> - <LinearLayout - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:orientation="vertical" - android:gravity="center"> - - <include layout="@layout/keyguard_navigation"/> - - <Button android:id="@+id/forgot_password_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="@dimen/kg_status_line_font_size" - android:visibility="gone"/> - - </LinearLayout> + <include layout="@layout/keyguard_navigation"/> <!-- We need MATCH_PARENT here only to force the size of the parent to be passed to the pattern view for it to compute its size. This is an unusual case, caused by @@ -69,7 +55,7 @@ android:layout_gravity="center_horizontal" android:gravity="center" /> - <include layout="@layout/keyguard_emergency_carrier_area" + <include layout="@layout/keyguard_emergency_carrier_area_and_recovery" android:id="@+id/keyguard_selector_fade_container" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml index e0a3ce3..80d9d61 100644 --- a/core/res/res/layout/keyguard_screen_password_landscape.xml +++ b/core/res/res/layout/keyguard_screen_password_landscape.xml @@ -143,7 +143,6 @@ android:layout_width="0dip" android:layout_weight="1" android:gravity="center" - android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left" android:layout_gravity="center_vertical" android:singleLine="true" android:textStyle="normal" diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml index 0212f73..3d61bae 100644 --- a/core/res/res/layout/keyguard_screen_password_portrait.xml +++ b/core/res/res/layout/keyguard_screen_password_portrait.xml @@ -106,12 +106,10 @@ android:layout_marginEnd="16dip"> <EditText android:id="@+id/passwordEntry" - android:layout_width="0dip" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_weight="1" android:gravity="center_horizontal" android:layout_gravity="center_vertical" - android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left" android:singleLine="true" android:textStyle="normal" android:inputType="textPassword" diff --git a/core/res/res/layout/keyguard_sim_pin_view.xml b/core/res/res/layout/keyguard_sim_pin_view.xml index 82268ad..163dc15 100644 --- a/core/res/res/layout/keyguard_sim_pin_view.xml +++ b/core/res/res/layout/keyguard_sim_pin_view.xml @@ -43,7 +43,7 @@ android:layout_height="wrap_content" android:src="@drawable/ic_lockscreen_sim"/> - <include layout="@layout/keyguard_sim_puk_pin_navigation"/> + <include layout="@layout/keyguard_sim_puk_pin_account_navigation"/> </LinearLayout> <!-- Password entry field --> diff --git a/core/res/res/layout/keyguard_sim_puk_pin_navigation.xml b/core/res/res/layout/keyguard_sim_puk_pin_account_navigation.xml index 2e6fa37..2e6fa37 100644 --- a/core/res/res/layout/keyguard_sim_puk_pin_navigation.xml +++ b/core/res/res/layout/keyguard_sim_puk_pin_account_navigation.xml diff --git a/core/res/res/layout/keyguard_sim_puk_view.xml b/core/res/res/layout/keyguard_sim_puk_view.xml index 6404efc..6e45b0b 100644 --- a/core/res/res/layout/keyguard_sim_puk_view.xml +++ b/core/res/res/layout/keyguard_sim_puk_view.xml @@ -44,7 +44,7 @@ android:layout_height="wrap_content" android:src="@drawable/ic_lockscreen_sim"/> - <include layout="@layout/keyguard_sim_puk_pin_navigation"/> + <include layout="@layout/keyguard_sim_puk_pin_account_navigation"/> </LinearLayout> diff --git a/core/res/res/layout/keyguard_status_view.xml b/core/res/res/layout/keyguard_status_view.xml index a462c54..1de0f6c 100644 --- a/core/res/res/layout/keyguard_status_view.xml +++ b/core/res/res/layout/keyguard_status_view.xml @@ -33,28 +33,32 @@ android:gravity="center_horizontal|top" android:contentDescription="@*android:string/keyguard_accessibility_status"> - <com.android.internal.policy.impl.keyguard.ClockView - android:id="@+id/clock_view" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/kg_clock_top_margin" - android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" - android:layout_gravity="right"> - - <TextView android:id="@+id/clock_text" + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:orientation="vertical"> + <com.android.internal.policy.impl.keyguard.ClockView + android:id="@+id/clock_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:singleLine="true" - android:ellipsize="none" - android:textSize="@dimen/kg_status_clock_font_size" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="#ffffffff" - android:drawablePadding="2dip" - /> + android:layout_marginEnd="@dimen/kg_status_line_font_right_margin" + android:layout_gravity="right"> + + <TextView android:id="@+id/clock_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="none" + android:textSize="@dimen/kg_status_clock_font_size" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="#ffffffff" + android:drawablePadding="2dip" + /> - </com.android.internal.policy.impl.keyguard.ClockView> + </com.android.internal.policy.impl.keyguard.ClockView> - <include layout="@layout/keyguard_status_area" /> + <include layout="@layout/keyguard_status_area" /> + </LinearLayout> </com.android.internal.policy.impl.keyguard.KeyguardStatusView> </com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame> diff --git a/core/res/res/values-land/bools.xml b/core/res/res/values-land/bools.xml index 4dd9369..b0630ad 100644 --- a/core/res/res/values-land/bools.xml +++ b/core/res/res/values-land/bools.xml @@ -16,5 +16,5 @@ <resources> <bool name="kg_share_status_area">false</bool> - <bool name="kg_sim_puk_full_screen">false</bool> + <bool name="kg_sim_puk_account_full_screen">false</bool> </resources> diff --git a/core/res/res/values-port/bools.xml b/core/res/res/values-port/bools.xml index 1597af3..1e2a4f2 100644 --- a/core/res/res/values-port/bools.xml +++ b/core/res/res/values-port/bools.xml @@ -17,5 +17,5 @@ <resources> <bool name="action_bar_embed_tabs">false</bool> <bool name="kg_share_status_area">true</bool> - <bool name="kg_sim_puk_full_screen">true</bool> + <bool name="kg_sim_puk_account_full_screen">true</bool> </resources> diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml index 355c52c..3753aba 100644 --- a/core/res/res/values-sw600dp/bools.xml +++ b/core/res/res/values-sw600dp/bools.xml @@ -18,5 +18,5 @@ <bool name="target_honeycomb_needs_options_menu">false</bool> <bool name="show_ongoing_ime_switcher">true</bool> <bool name="kg_share_status_area">false</bool> - <bool name="kg_sim_puk_full_screen">false</bool> + <bool name="kg_sim_puk_account_full_screen">false</bool> </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 31d4ad7..948a3d3 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -291,10 +291,10 @@ <dimen name="kg_widget_pager_horizontal_padding">16dp</dimen> <!-- Top padding for the widget pager --> - <dimen name="kg_widget_pager_top_padding">16dp</dimen> + <dimen name="kg_widget_pager_top_padding">0dp</dimen> <!-- Bottom padding for the widget pager --> - <dimen name="kg_widget_pager_bottom_padding">6dp</dimen> + <dimen name="kg_widget_pager_bottom_padding">0dp</dimen> <!-- Top margin for the runway lights. We add a negative margin in large devices to account for the widget pager padding --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 61838cc..e76b67b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1192,7 +1192,7 @@ <java-symbol type="bool" name="config_reverseDefaultRotation" /> <java-symbol type="bool" name="config_showNavigationBar" /> <java-symbol type="bool" name="kg_share_status_area" /> - <java-symbol type="bool" name="kg_sim_puk_full_screen" /> + <java-symbol type="bool" name="kg_sim_puk_account_full_screen" /> <java-symbol type="bool" name="target_honeycomb_needs_options_menu" /> <java-symbol type="color" name="kg_multi_user_text_active" /> <java-symbol type="color" name="kg_multi_user_text_inactive" /> diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index cc536f2..2b50091 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -2427,17 +2427,39 @@ status_t OpenGLRenderer::drawOval(float left, float top, float right, float bott } status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom, - float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) { - if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone; + float startAngle, float sweepAngle, bool useCenter, SkPaint* p) { + if (mSnapshot->isIgnored() || quickRejectPreStroke(left, top, right, bottom, p)) { + return DrawGlInfo::kStatusDone; + } if (fabs(sweepAngle) >= 360.0f) { - return drawOval(left, top, right, bottom, paint); + return drawOval(left, top, right, bottom, p); } - mCaches.activeTexture(0); - const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top, - startAngle, sweepAngle, useCenter, paint); - return drawShape(left, top, texture, paint); + // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180) + if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || p->getStrokeCap() != SkPaint::kButt_Cap) { + mCaches.activeTexture(0); + const PathTexture* texture = mCaches.arcShapeCache.getArc(right - left, bottom - top, + startAngle, sweepAngle, useCenter, p); + return drawShape(left, top, texture, p); + } + + SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); + if (p->getStyle() == SkPaint::kStrokeAndFill_Style) { + rect.outset(p->getStrokeWidth() / 2, p->getStrokeWidth() / 2); + } + + SkPath path; + if (useCenter) { + path.moveTo(rect.centerX(), rect.centerY()); + } + path.arcTo(rect, startAngle, sweepAngle, !useCenter); + if (useCenter) { + path.close(); + } + drawConvexPath(path, p); + + return DrawGlInfo::kStatusDrew; } // See SkPaintDefaults.h diff --git a/libs/hwui/PathRenderer.cpp b/libs/hwui/PathRenderer.cpp index 58d6cb8..dd13d79 100644 --- a/libs/hwui/PathRenderer.cpp +++ b/libs/hwui/PathRenderer.cpp @@ -80,11 +80,24 @@ inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) { * * Note that we can't add and normalize the two vectors, that would result in a rectangle having an * offset of (sqrt(2)/2, sqrt(2)/2) at each corner, instead of (1, 1) + * + * NOTE: assumes angles between normals 90 degrees or less */ inline vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) { return (normalA + normalB) / (1 + fabs(normalA.dot(normalB))); } +inline void scaleOffsetForStrokeWidth(vec2& offset, float halfStrokeWidth, + float inverseScaleX, float inverseScaleY) { + if (halfStrokeWidth == 0.0f) { + // hairline - compensate for scale + offset.x *= 0.5f * inverseScaleX; + offset.y *= 0.5f * inverseScaleY; + } else { + offset *= halfStrokeWidth; + } +} + void getFillVerticesFromPerimeter(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer) { Vertex* buffer = vertexBuffer.alloc<Vertex>(perimeter.size()); @@ -119,13 +132,7 @@ void getStrokeVerticesFromPerimeter(const Vector<Vertex>& perimeter, float halfS nextNormal.normalize(); vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); - if (halfStrokeWidth == 0.0f) { - // hairline - compensate for scale - totalOffset.x *= 0.5f * inverseScaleX; - totalOffset.y *= 0.5f * inverseScaleY; - } else { - totalOffset *= halfStrokeWidth; - } + scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); Vertex::set(&buffer[currentIndex++], current->position[0] + totalOffset.x, @@ -145,6 +152,55 @@ void getStrokeVerticesFromPerimeter(const Vector<Vertex>& perimeter, float halfS copyVertex(&buffer[currentIndex++], &buffer[1]); } +void getStrokeVerticesFromUnclosedVertices(const Vector<Vertex>& vertices, float halfStrokeWidth, + VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { + Vertex* buffer = vertexBuffer.alloc<Vertex>(vertices.size() * 2); + + int currentIndex = 0; + const Vertex* current = &(vertices[0]); + vec2 lastNormal; + for (unsigned int i = 0; i < vertices.size() - 1; i++) { + const Vertex* next = &(vertices[i + 1]); + vec2 nextNormal(next->position[1] - current->position[1], + current->position[0] - next->position[0]); + nextNormal.normalize(); + + vec2 totalOffset; + if (i == 0) { + totalOffset = nextNormal; + } else { + totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); + } + scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); + + Vertex::set(&buffer[currentIndex++], + current->position[0] + totalOffset.x, + current->position[1] + totalOffset.y); + + Vertex::set(&buffer[currentIndex++], + current->position[0] - totalOffset.x, + current->position[1] - totalOffset.y); + + current = next; + lastNormal = nextNormal; + } + + vec2 totalOffset = lastNormal; + scaleOffsetForStrokeWidth(totalOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); + + Vertex::set(&buffer[currentIndex++], + current->position[0] + totalOffset.x, + current->position[1] + totalOffset.y); + Vertex::set(&buffer[currentIndex++], + current->position[0] - totalOffset.x, + current->position[1] - totalOffset.y); +#if VERTEX_DEBUG + for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { + ALOGD("point at %f %f", buffer[i].position[0], buffer[i].position[1]); + } +#endif +} + void getFillVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(perimeter.size() * 3 + 2); @@ -202,11 +258,167 @@ void getFillVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, VertexBuffe #if VERTEX_DEBUG for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { - ALOGD("point at %f %f", buffer[i].position[0], buffer[i].position[1]); + ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); + } +#endif +} + + +void getStrokeVerticesFromUnclosedVerticesAA(const Vector<Vertex>& vertices, float halfStrokeWidth, + VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { + AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * vertices.size() + 2); + + // avoid lines smaller than hairline since they break triangle based sampling. instead reducing + // alpha value (TODO: support different X/Y scale) + float maxAlpha = 1.0f; + if (halfStrokeWidth != 0 && inverseScaleX == inverseScaleY && + halfStrokeWidth * inverseScaleX < 0.5f) { + maxAlpha *= (2 * halfStrokeWidth) / inverseScaleX; + halfStrokeWidth = 0.0f; + } + + // there is no outer/inner here, using them for consistency with below approach + int offset = 2 * (vertices.size() - 2); + int currentAAOuterIndex = 2; + int currentAAInnerIndex = 2 * offset + 5; // reversed + int currentStrokeIndex = currentAAInnerIndex + 7; + + const Vertex* last = &(vertices[0]); + const Vertex* current = &(vertices[1]); + vec2 lastNormal(current->position[1] - last->position[1], + last->position[0] - current->position[0]); + lastNormal.normalize(); + + { + // start cap + vec2 totalOffset = lastNormal; + vec2 AAOffset = totalOffset; + AAOffset.x *= 0.5f * inverseScaleX; + AAOffset.y *= 0.5f * inverseScaleY; + + vec2 innerOffset = totalOffset; + scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); + vec2 outerOffset = innerOffset + AAOffset; + innerOffset -= AAOffset; + + // TODO: support square cap by changing this offset to incorporate halfStrokeWidth + vec2 capAAOffset(AAOffset.y, -AAOffset.x); + AlphaVertex::set(&buffer[0], + last->position[0] + outerOffset.x + capAAOffset.x, + last->position[1] + outerOffset.y + capAAOffset.y, + 0.0f); + AlphaVertex::set(&buffer[1], + last->position[0] + innerOffset.x - capAAOffset.x, + last->position[1] + innerOffset.y - capAAOffset.y, + maxAlpha); + + AlphaVertex::set(&buffer[2 * offset + 6], + last->position[0] - outerOffset.x + capAAOffset.x, + last->position[1] - outerOffset.y + capAAOffset.y, + 0.0f); + AlphaVertex::set(&buffer[2 * offset + 7], + last->position[0] - innerOffset.x - capAAOffset.x, + last->position[1] - innerOffset.y - capAAOffset.y, + maxAlpha); + copyAlphaVertex(&buffer[2 * offset + 8], &buffer[0]); + copyAlphaVertex(&buffer[2 * offset + 9], &buffer[1]); + copyAlphaVertex(&buffer[2 * offset + 10], &buffer[1]); // degenerate tris (the only two!) + copyAlphaVertex(&buffer[2 * offset + 11], &buffer[2 * offset + 7]); + } + + for (unsigned int i = 1; i < vertices.size() - 1; i++) { + const Vertex* next = &(vertices[i + 1]); + vec2 nextNormal(next->position[1] - current->position[1], + current->position[0] - next->position[0]); + nextNormal.normalize(); + + vec2 totalOffset = totalOffsetFromNormals(lastNormal, nextNormal); + vec2 AAOffset = totalOffset; + AAOffset.x *= 0.5f * inverseScaleX; + AAOffset.y *= 0.5f * inverseScaleY; + + vec2 innerOffset = totalOffset; + scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); + vec2 outerOffset = innerOffset + AAOffset; + innerOffset -= AAOffset; + + AlphaVertex::set(&buffer[currentAAOuterIndex++], + current->position[0] + outerOffset.x, + current->position[1] + outerOffset.y, + 0.0f); + AlphaVertex::set(&buffer[currentAAOuterIndex++], + current->position[0] + innerOffset.x, + current->position[1] + innerOffset.y, + maxAlpha); + + AlphaVertex::set(&buffer[currentStrokeIndex++], + current->position[0] + innerOffset.x, + current->position[1] + innerOffset.y, + maxAlpha); + AlphaVertex::set(&buffer[currentStrokeIndex++], + current->position[0] - innerOffset.x, + current->position[1] - innerOffset.y, + maxAlpha); + + AlphaVertex::set(&buffer[currentAAInnerIndex--], + current->position[0] - innerOffset.x, + current->position[1] - innerOffset.y, + maxAlpha); + AlphaVertex::set(&buffer[currentAAInnerIndex--], + current->position[0] - outerOffset.x, + current->position[1] - outerOffset.y, + 0.0f); + + last = current; + current = next; + lastNormal = nextNormal; + } + + { + // end cap + vec2 totalOffset = lastNormal; + vec2 AAOffset = totalOffset; + AAOffset.x *= 0.5f * inverseScaleX; + AAOffset.y *= 0.5f * inverseScaleY; + + vec2 innerOffset = totalOffset; + scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); + vec2 outerOffset = innerOffset + AAOffset; + innerOffset -= AAOffset; + + // TODO: support square cap by changing this offset to incorporate halfStrokeWidth + vec2 capAAOffset(-AAOffset.y, AAOffset.x); + + AlphaVertex::set(&buffer[offset + 2], + current->position[0] + outerOffset.x + capAAOffset.x, + current->position[1] + outerOffset.y + capAAOffset.y, + 0.0f); + AlphaVertex::set(&buffer[offset + 3], + current->position[0] + innerOffset.x - capAAOffset.x, + current->position[1] + innerOffset.y - capAAOffset.y, + maxAlpha); + + AlphaVertex::set(&buffer[offset + 4], + current->position[0] - outerOffset.x + capAAOffset.x, + current->position[1] - outerOffset.y + capAAOffset.y, + 0.0f); + AlphaVertex::set(&buffer[offset + 5], + current->position[0] - innerOffset.x - capAAOffset.x, + current->position[1] - innerOffset.y - capAAOffset.y, + maxAlpha); + + copyAlphaVertex(&buffer[vertexBuffer.getSize() - 2], &buffer[offset + 3]); + copyAlphaVertex(&buffer[vertexBuffer.getSize() - 1], &buffer[offset + 5]); + } + +#if VERTEX_DEBUG + for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { + ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); } #endif } + void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float halfStrokeWidth, VertexBuffer& vertexBuffer, float inverseScaleX, float inverseScaleY) { AlphaVertex* buffer = vertexBuffer.alloc<AlphaVertex>(6 * perimeter.size() + 8); @@ -242,13 +454,7 @@ void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float hal AAOffset.y *= 0.5f * inverseScaleY; vec2 innerOffset = totalOffset; - if (halfStrokeWidth == 0.0f) { - // hairline! - compensate for scale - innerOffset.x *= 0.5f * inverseScaleX; - innerOffset.y *= 0.5f * inverseScaleY; - } else { - innerOffset *= halfStrokeWidth; - } + scaleOffsetForStrokeWidth(innerOffset, halfStrokeWidth, inverseScaleX, inverseScaleY); vec2 outerOffset = innerOffset + AAOffset; innerOffset -= AAOffset; @@ -296,6 +502,12 @@ void getStrokeVerticesFromPerimeterAA(const Vector<Vertex>& perimeter, float hal copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset]); copyAlphaVertex(&buffer[currentAAInnerIndex++], &buffer[2 * offset + 1]); // don't need to create last degenerate tri + +#if VERTEX_DEBUG + for (unsigned int i = 0; i < vertexBuffer.getSize(); i++) { + ALOGD("point at %f %f, alpha %f", buffer[i].position[0], buffer[i].position[1], buffer[i].alpha); + } +#endif } void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint, @@ -320,7 +532,10 @@ void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint, threshInvScaleY *= bounds.height() / (bounds.height() + paint->getStrokeWidth()); } } - convexPathPerimeterVertices(path, threshInvScaleX * threshInvScaleX, + + // force close if we're filling the path, since fill path expects closed perimeter. + bool forceClose = style != SkPaint::kStroke_Style; + bool wasClosed = convexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX, threshInvScaleY * threshInvScaleY, tempVertices); if (!tempVertices.size()) { @@ -337,11 +552,22 @@ void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint, if (style == SkPaint::kStroke_Style) { float halfStrokeWidth = paint->getStrokeWidth() * 0.5f; if (!isAA) { - getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer, - inverseScaleX, inverseScaleY); + if (wasClosed) { + getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer, + inverseScaleX, inverseScaleY); + } else { + getStrokeVerticesFromUnclosedVertices(tempVertices, halfStrokeWidth, vertexBuffer, + inverseScaleX, inverseScaleY); + } + } else { - getStrokeVerticesFromPerimeterAA(tempVertices, halfStrokeWidth, vertexBuffer, - inverseScaleX, inverseScaleY); + if (wasClosed) { + getStrokeVerticesFromPerimeterAA(tempVertices, halfStrokeWidth, vertexBuffer, + inverseScaleX, inverseScaleY); + } else { + getStrokeVerticesFromUnclosedVerticesAA(tempVertices, halfStrokeWidth, vertexBuffer, + inverseScaleX, inverseScaleY); + } } } else { // For kStrokeAndFill style, the path should be adjusted externally, as it will be treated as a fill here. @@ -354,19 +580,27 @@ void PathRenderer::convexPathVertices(const SkPath &path, const SkPaint* paint, } -void PathRenderer::convexPathPerimeterVertices(const SkPath& path, +void pushToVector(Vector<Vertex>& vertices, float x, float y) { + // TODO: make this not yuck + vertices.push(); + Vertex* newVertex = &(vertices.editArray()[vertices.size() - 1]); + Vertex::set(newVertex, x, y); +} + +bool PathRenderer::convexPathPerimeterVertices(const SkPath& path, bool forceClose, float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) { ATRACE_CALL(); - SkPath::Iter iter(path, true); - SkPoint pos; + // TODO: to support joins other than sharp miter, join vertices should be labelled in the + // perimeter, or resolved into more vertices. Reconsider forceClose-ing in that case. + SkPath::Iter iter(path, forceClose); SkPoint pts[4]; SkPath::Verb v; Vertex* newVertex = 0; while (SkPath::kDone_Verb != (v = iter.next(pts))) { switch (v) { case SkPath::kMove_Verb: - pos = pts[0]; + pushToVector(outputVertices, pts[0].x(), pts[0].y()); ALOGV("Move to pos %f %f", pts[0].x(), pts[0].y()); break; case SkPath::kClose_Verb: @@ -377,10 +611,7 @@ void PathRenderer::convexPathPerimeterVertices(const SkPath& path, pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y()); - // TODO: make this not yuck - outputVertices.push(); - newVertex = &(outputVertices.editArray()[outputVertices.size() - 1]); - Vertex::set(newVertex, pts[1].x(), pts[1].y()); + pushToVector(outputVertices, pts[1].x(), pts[1].y()); break; case SkPath::kQuad_Verb: ALOGV("kQuad_Verb"); @@ -403,6 +634,14 @@ void PathRenderer::convexPathPerimeterVertices(const SkPath& path, break; } } + + int size = outputVertices.size(); + if (size >= 2 && outputVertices[0].position[0] == outputVertices[size - 1].position[0] && + outputVertices[0].position[1] == outputVertices[size - 1].position[1]) { + outputVertices.pop(); + return true; + } + return false; } void PathRenderer::recursiveCubicBezierVertices( @@ -419,10 +658,7 @@ void PathRenderer::recursiveCubicBezierVertices( if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) { // below thresh, draw line by adding endpoint - // TODO: make this not yuck - outputVertices.push(); - Vertex* newVertex = &(outputVertices.editArray()[outputVertices.size() - 1]); - Vertex::set(newVertex, p2x, p2y); + pushToVector(outputVertices, p2x, p2y); } else { float p1c1x = (p1x + c1x) * 0.5f; float p1c1y = (p1y + c1y) * 0.5f; @@ -463,10 +699,7 @@ void PathRenderer::recursiveQuadraticBezierVertices( if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) { // below thresh, draw line by adding endpoint - // TODO: make this not yuck - outputVertices.push(); - Vertex* newVertex = &(outputVertices.editArray()[outputVertices.size() - 1]); - Vertex::set(newVertex, bx, by); + pushToVector(outputVertices, bx, by); } else { float acx = (ax + cx) * 0.5f; float bcx = (bx + cx) * 0.5f; diff --git a/libs/hwui/PathRenderer.h b/libs/hwui/PathRenderer.h index 28a5b90..e9f347b 100644 --- a/libs/hwui/PathRenderer.h +++ b/libs/hwui/PathRenderer.h @@ -71,10 +71,8 @@ public: const mat4 *transform, VertexBuffer& vertexBuffer); private: - static void convexPathPerimeterVertices( - const SkPath &path, - float sqrInvScaleX, float sqrInvScaleY, - Vector<Vertex> &outputVertices); + static bool convexPathPerimeterVertices(const SkPath &path, bool forceClose, + float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex> &outputVertices); /* endpoints a & b, diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index f26d322..f77cbfb 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -153,11 +153,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished { private static final int MSG_SET_A2DP_CONNECTION_STATE = 22; // end of messages handled under wakelock private static final int MSG_SET_RSX_CONNECTION_STATE = 23; // change remote submix connection - private static final int MSG_SET_FORCE_RSX_USE = 24; // force remote submix audio routing - private static final int MSG_CHECK_MUSIC_ACTIVE = 25; - private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 26; - private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 27; - private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 28; + private static final int MSG_CHECK_MUSIC_ACTIVE = 24; + private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 25; + private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 26; + private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 27; // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be // persisted @@ -2221,13 +2220,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished { on ? 1 : 0 /*arg1*/, address /*arg2*/, null/*obj*/, 0/*delay*/); - - // Note that we are currently forcing use of remote submix as soon as corresponding device - // is made available - sendMsg(mAudioHandler, MSG_SET_FORCE_RSX_USE, SENDMSG_REPLACE, - AudioSystem.FOR_MEDIA, - on ? AudioSystem.FORCE_REMOTE_SUBMIX : AudioSystem.FORCE_NONE, - null/*obj*/, 0/*delay*/); } private void onSetRsxConnectionState(int available, int address) { @@ -3320,7 +3312,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished { case MSG_SET_FORCE_USE: case MSG_SET_FORCE_BT_A2DP_USE: - case MSG_SET_FORCE_RSX_USE: setForceUse(msg.arg1, msg.arg2); break; diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 260ddc7..dde2979 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -360,9 +360,8 @@ public class AudioSystem public static final int FORCE_ANALOG_DOCK = 8; public static final int FORCE_DIGITAL_DOCK = 9; public static final int FORCE_NO_BT_A2DP = 10; - public static final int FORCE_REMOTE_SUBMIX = 11; - public static final int FORCE_SYSTEM_ENFORCED = 12; - private static final int NUM_FORCE_CONFIG = 13; + public static final int FORCE_SYSTEM_ENFORCED = 11; + private static final int NUM_FORCE_CONFIG = 12; public static final int FORCE_DEFAULT = FORCE_NONE; // usage for setForceUse, must match AudioSystem::force_use diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java index 4756078..f4fccbe 100644 --- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java +++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java @@ -3831,6 +3831,7 @@ class MediaArtistNativeHelper { outWidth, outHeight, Bitmap.Config.ARGB_8888); // Copy int[] to IntBuffer + decBuffer.rewind(); decBuffer.put(decArray, 0, thumbnailSize); decBuffer.rewind(); diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_normal.png Binary files differnew file mode 100644 index 0000000..3ed7418 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_normal.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_pressed.png Binary files differnew file mode 100644 index 0000000..5e20eea --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_settings_pressed.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_normal.png Binary files differnew file mode 100644 index 0000000..44cfc5b --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_normal.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_pressed.png Binary files differnew file mode 100644 index 0000000..0c3fdcd --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_settings_pressed.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_normal.png Binary files differnew file mode 100644 index 0000000..80fdb79 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_normal.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_pressed.png Binary files differnew file mode 100644 index 0000000..ac7c1a7 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_settings_pressed.png diff --git a/packages/SystemUI/res/drawable/ic_notify_settings.xml b/packages/SystemUI/res/drawable/ic_notify_settings.xml new file mode 100644 index 0000000..6579d8e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_notify_settings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" + android:drawable="@drawable/ic_notify_settings_pressed" /> + <item + android:drawable="@drawable/ic_notify_settings_normal" /> +</selector> + diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml index f1a8d82..c921837 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml @@ -75,14 +75,14 @@ android:layout_width="50dp" android:layout_height="50dp" android:scaleType="center" - android:src="@drawable/ic_notify_quicksettings" + android:src="@drawable/ic_notify_settings" android:contentDescription="@string/accessibility_settings_button" /> <ImageView android:id="@+id/clear_all_button" android:layout_width="50dp" android:layout_height="50dp" - android:layout_marginLeft="18dp" + android:layout_marginLeft="12dp" android:scaleType="center" android:src="@drawable/ic_notify_clear" android:contentDescription="@string/accessibility_clear_all" diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 4b895ec..07aca6c 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -42,20 +42,11 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> - <include layout="@layout/quick_settings" + <ViewStub android:id="@+id/quick_settings_stub" + android:layout="@layout/quick_settings" android:layout_width="match_parent" android:layout_height="match_parent" /> </com.android.systemui.statusbar.phone.PanelHolder> - <ViewStub - android:layout="@layout/status_bar_help" - android:id="@+id/status_bar_cling_stub" - android:inflatedId="@+id/status_bar_cling" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginTop="@*android:dimen/status_bar_height" - android:visibility="gone" - /> - </com.android.systemui.statusbar.phone.StatusBarWindowView> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index 209ad11..50575d0 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -20,6 +20,9 @@ <!-- These resources are around just to allow their values to be customized for different hardware and product builds. --> <resources> + <!-- Enable quick settings on tablets --> + <bool name="config_hasSettingsPanel">true</bool> + <!-- The number of columns in the QuickSettings --> <integer name="quick_settings_num_columns">3</integer> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 942e814..aec9555 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -97,5 +97,7 @@ <integer name="blinds_pop_duration_ms">10</integer> + <!-- Disable quick settings by default --> + <bool name="config_hasSettingsPanel">false</bool> </resources> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 4a73200..2cc3446 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -19,4 +19,5 @@ <item type="id" name="expandable_tag" /> <item type="id" name="user_expanded_tag" /> <item type="id" name="user_lock_tag" /> + <item type="id" name="status_bar_cling_stub" /> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index a874c6d..6877cba 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -156,7 +156,7 @@ public class ImageWallpaper extends WallpaperService { mBackgroundWidth = mBackgroundHeight = -1; mBackground = null; mRedrawNeeded = true; - drawFrameLocked(); + drawFrameLocked(false); } } } @@ -234,7 +234,7 @@ public class ImageWallpaper extends WallpaperService { Log.d(TAG, "Visibility changed to visible=" + visible); } mVisible = visible; - drawFrameLocked(); + drawFrameLocked(false); } } } @@ -263,7 +263,7 @@ public class ImageWallpaper extends WallpaperService { mYOffset = yOffset; mOffsetsChanged = true; } - drawFrameLocked(); + drawFrameLocked(false); } } @@ -277,7 +277,8 @@ public class ImageWallpaper extends WallpaperService { synchronized (mLock) { mRedrawNeeded = true; - drawFrameLocked(); + mBackgroundWidth = mBackgroundHeight = -1; + drawFrameLocked(true); } } @@ -290,25 +291,26 @@ public class ImageWallpaper extends WallpaperService { synchronized (mLock) { mRedrawNeeded = true; - drawFrameLocked(); + drawFrameLocked(false); } } - void drawFrameLocked() { - if (!mVisible) { - if (DEBUG) { - Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible."); + void drawFrameLocked(boolean force) { + if (!force) { + if (!mVisible) { + if (DEBUG) { + Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible."); + } + return; } - return; - } - if (!mRedrawNeeded && !mOffsetsChanged) { - if (DEBUG) { - Log.d(TAG, "Suppressed drawFrame since redraw is not needed " - + "and offsets have not changed."); + if (!mRedrawNeeded && !mOffsetsChanged) { + if (DEBUG) { + Log.d(TAG, "Suppressed drawFrame since redraw is not needed " + + "and offsets have not changed."); + } + return; } - return; } - // If we don't yet know the size of the wallpaper bitmap, // we need to get it now. boolean updateWallpaper = mBackgroundWidth < 0 || mBackgroundHeight < 0 ; @@ -332,7 +334,8 @@ public class ImageWallpaper extends WallpaperService { int yPixels = availh < 0 ? (int)(availh * mYOffset + .5f) : (availh / 2); mOffsetsChanged = false; - if (!mRedrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) { + if (!force && !mRedrawNeeded + && xPixels == mLastXTranslation && yPixels == mLastYTranslation) { if (DEBUG) { Log.d(TAG, "Suppressed drawFrame since the image has not " + "actually moved an integral number of pixels."); @@ -343,6 +346,11 @@ public class ImageWallpaper extends WallpaperService { mLastXTranslation = xPixels; mLastYTranslation = yPixels; + if (DEBUG) { + Log.d(TAG, "drawFrameUnlocked(" + force + "): mBackgroundWxH=" + mBackgroundWidth + "x" + + mBackgroundHeight + " SurfaceFrame=" + frame.toShortString() + + " X,YOffset=" + mXOffset + "," + mYOffset); + } if (mIsHwAccelerated) { if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) { drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels); @@ -657,6 +665,7 @@ public class ImageWallpaper extends WallpaperService { EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, + EGL_CONFIG_CAVEAT, EGL_NONE, EGL_NONE }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index 3fd413a..d0fc340 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -57,9 +57,9 @@ public class PanelBar extends FrameLayout { mPanelHolder = ph; final int N = ph.getChildCount(); for (int i=0; i<N; i++) { - final PanelView v = (PanelView) ph.getChildAt(i); - if (v != null) { - addPanel(v); + final View v = ph.getChildAt(i); + if (v != null && v instanceof PanelView) { + addPanel((PanelView) v); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index d68151d..75a2598 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -188,12 +188,13 @@ public class PhoneStatusBar extends BaseStatusBar { TextView mNotificationPanelDebugText; // settings + boolean mHasSettingsPanel; SettingsPanelView mSettingsPanel; int mSettingsPanelGravity; // top bar View mClearButton; - View mSettingsButton; + ImageView mSettingsButton; // carrier/wifi label private TextView mCarrierLabel; @@ -420,13 +421,25 @@ public class PhoneStatusBar extends BaseStatusBar { mClearButton.setVisibility(View.INVISIBLE); mClearButton.setEnabled(false); mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date); - mSettingsButton = mStatusBarWindow.findViewById(R.id.settings_button); + + mHasSettingsPanel = res.getBoolean(R.bool.config_hasSettingsPanel); + + mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button); if (mSettingsButton != null) { - if (mStatusBarView.hasFullWidthNotifications()) { - mSettingsButton.setOnClickListener(mSettingsButtonListener); - mSettingsButton.setVisibility(View.VISIBLE); + mSettingsButton.setOnClickListener(mSettingsButtonListener); + if (mHasSettingsPanel) { + if (mStatusBarView.hasFullWidthNotifications()) { + // the settings panel is hiding behind this button + mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); + mSettingsButton.setVisibility(View.VISIBLE); + } else { + // there is a settings panel, but it's on the other side of the (large) screen + mSettingsButton.setVisibility(View.GONE); + } } else { - mSettingsButton.setVisibility(View.GONE); + // no settings panel, go straight to settings + mSettingsButton.setVisibility(View.VISIBLE); + mSettingsButton.setImageResource(R.drawable.ic_notify_settings); } } @@ -490,18 +503,31 @@ public class PhoneStatusBar extends BaseStatusBar { }); } - // Quick Settings (WIP) - mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel); - mSettingsPanel.setBar(mStatusBarView); - mSettingsPanel.setService(this); - mSettingsPanel.setup(mNetworkController, mBluetoothController, mBatteryController, - mLocationController); - mSettingsPanel.setSystemUiVisibility( - View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER | View.STATUS_BAR_DISABLE_SYSTEM_INFO); + // Quick Settings (where available, some restrictions apply) + if (mHasSettingsPanel) { + final View settings_stub + = mStatusBarWindow.findViewById(R.id.quick_settings_stub); - if (!ActivityManager.isHighEndGfx()) { - mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor( - R.color.notification_panel_solid_background))); + if (settings_stub != null) { + mSettingsPanel = (SettingsPanelView) ((ViewStub)settings_stub).inflate(); + } else { + mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel); + } + + if (mSettingsPanel != null) { + mSettingsPanel.setBar(mStatusBarView); + mSettingsPanel.setService(this); + mSettingsPanel.setup(mNetworkController, mBluetoothController, mBatteryController, + mLocationController); + mSettingsPanel.setSystemUiVisibility( + View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER + | View.STATUS_BAR_DISABLE_SYSTEM_INFO); + + if (!ActivityManager.isHighEndGfx()) { + mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor( + R.color.notification_panel_solid_background))); + } + } } mClingShown = ! (DEBUG_CLINGS @@ -1286,7 +1312,7 @@ public class PhoneStatusBar extends BaseStatusBar { return; } - mSettingsPanel.expand(); + if (mSettingsPanel != null) mSettingsPanel.expand(); if (false) postStartTracing(); } @@ -1596,7 +1622,7 @@ public class PhoneStatusBar extends BaseStatusBar { mCommandQueue.setNavigationIconHints( altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT) : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT)); - mSettingsPanel.setImeWindowStatus(vis > 0); + if (mSettingsPanel != null) mSettingsPanel.setImeWindowStatus(vis > 0); } @Override @@ -1820,10 +1846,12 @@ public class PhoneStatusBar extends BaseStatusBar { lp.leftMargin = mNotificationPanelMarginPx; mNotificationPanel.setLayoutParams(lp); - lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams(); - lp.gravity = mSettingsPanelGravity; - lp.rightMargin = mNotificationPanelMarginPx; - mSettingsPanel.setLayoutParams(lp); + if (mSettingsPanel != null) { + lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams(); + lp.gravity = mSettingsPanelGravity; + lp.rightMargin = mNotificationPanelMarginPx; + mSettingsPanel.setLayoutParams(lp); + } updateCarrierLabelVisibility(false); } @@ -1916,7 +1944,19 @@ public class PhoneStatusBar extends BaseStatusBar { private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() { public void onClick(View v) { - animateExpandSettingsPanel(); + if (mHasSettingsPanel) { + animateExpandSettingsPanel(); + } else { + try { + // Dismiss the lock screen when Settings starts. + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); + } catch (RemoteException e) { + } + Intent intent = new Intent(android.provider.Settings.ACTION_SETTINGS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); + animateCollapsePanels(); + } } }; @@ -2010,7 +2050,7 @@ public class PhoneStatusBar extends BaseStatusBar { } // Update the QuickSettings container - mSettingsPanel.updateResources(); + if (mSettingsPanel != null) mSettingsPanel.updateResources(); loadDimens(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 96f729e..3c2f0e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -109,7 +109,8 @@ public class PhoneStatusBarView extends PanelBar { if (mFullWidthNotifications) { // No double swiping. If either panel is open, nothing else can be pulled down. - return (mSettingsPanel.getExpandedHeight() + mNotificationPanel.getExpandedHeight()> 0) + return ((mSettingsPanel == null ? 0 : mSettingsPanel.getExpandedHeight()) + + mNotificationPanel.getExpandedHeight() > 0) ? null : mNotificationPanel; } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index e8af0a5..91d5eaa 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -1473,16 +1473,24 @@ public class PhoneWindowManager implements WindowManagerPolicy { return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation); } + @Override public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) { return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD; } + @Override public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) { - return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR - && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR - && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER - && attrs.type != WindowManager.LayoutParams.TYPE_DREAM - && attrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND; + switch (attrs.type) { + case TYPE_STATUS_BAR: + case TYPE_NAVIGATION_BAR: + case TYPE_WALLPAPER: + case TYPE_DREAM: + case TYPE_UNIVERSE_BACKGROUND: + case TYPE_KEYGUARD: + return false; + default: + return true; + } } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java index 57239c3..ebca4ac 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java @@ -84,6 +84,9 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit protected void onFinishInflate() { super.onFinishInflate(); + // We always set a dummy NavigationManager to avoid null checks + mSecurityMessageDisplay = new KeyguardNavigationManager(null); + mLogin = (EditText) findViewById(R.id.login); mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } ); mLogin.addTextChangedListener(this); @@ -137,8 +140,9 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit mLogin.setText(""); mPassword.setText(""); mLogin.requestFocus(); - mSecurityMessageDisplay.setMessage(mLockPatternUtils.isPermanentlyLocked() ? - R.string.kg_login_too_many_attempts : R.string.kg_login_instructions); + boolean permLocked = mLockPatternUtils.isPermanentlyLocked(); + mSecurityMessageDisplay.setMessage(permLocked ? R.string.kg_login_too_many_attempts : + R.string.kg_login_instructions, permLocked ? true : false); } /** {@inheritDoc} */ @@ -178,7 +182,7 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit // dismiss keyguard mCallback.dismiss(true); } else { - mSecurityMessageDisplay.setMessage(R.string.kg_login_invalid_input); + mSecurityMessageDisplay.setMessage(R.string.kg_login_invalid_input, true); mPassword.setText(""); mCallback.reportFailedUnlockAttempt(); } @@ -314,7 +318,8 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit @Override public void setSecurityMessageDisplay(SecurityMessageDisplay display) { - mSecurityMessageDisplay = display; + mSecurityMessageDisplay = display; + reset(); } } 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 4987020..ebc54b3 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -79,7 +79,7 @@ public class KeyguardHostView extends KeyguardViewBase { private boolean mEnableMenuKey; private boolean mIsVerifyUnlockOnly; private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView - private SecurityMode mCurrentSecuritySelection = SecurityMode.None; + private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid; protected Runnable mLaunchRunnable; @@ -162,7 +162,7 @@ public class KeyguardHostView extends KeyguardViewBase { addDefaultWidgets(); updateSecurityViews(); setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK); - + if (KeyguardUpdateMonitor.getInstance(mContext).getIsFirstBoot()) { showPrimarySecurityScreen(false); } @@ -195,7 +195,8 @@ public class KeyguardHostView extends KeyguardViewBase { protected void onAttachedToWindow() { super.onAttachedToWindow(); mAppWidgetHost.startListening(); - maybePopulateWidgets(); + // TODO: Re-enable when we have layouts that can support a better variety of widgets. + // maybePopulateWidgets(); disableStatusViewInteraction(); post(mSwitchPageRunnable); } @@ -424,7 +425,7 @@ public class KeyguardHostView extends KeyguardViewBase { } showSecurityScreen(securityMode); } - + /** * Shows the backup security screen for the current security mode. This could be used for * password recovery screens but is currently only used for pattern unlock to show the @@ -432,7 +433,8 @@ public class KeyguardHostView extends KeyguardViewBase { */ private void showBackupSecurityScreen() { if (DEBUG) Log.d(TAG, "showBackupSecurity()"); - showSecurityScreen(mSecurityModel.getBackupSecurityMode()); + SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection); + showSecurityScreen(backup); } public boolean showNextSecurityScreenIfPresent() { @@ -492,7 +494,7 @@ public class KeyguardHostView extends KeyguardViewBase { // enabled because the user has left keyguard. KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true); KeyguardUpdateMonitor.getInstance(mContext).setIsFirstBoot(false); - + // If there's a pending runnable because the user interacted with a widget // and we're leaving keyguard, then run it. if (mLaunchRunnable != null) { @@ -542,6 +544,45 @@ public class KeyguardHostView extends KeyguardViewBase { private KeyguardStatusViewManager mKeyguardStatusViewManager; + // Used to ignore callbacks from methods that are no longer current (e.g. face unlock). + // This avoids unwanted asynchronous events from messing with the state. + private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() { + + @Override + public void userActivity(long timeout) { + } + + @Override + public void showBackupSecurity() { + } + + @Override + public void setOnDismissRunnable(Runnable runnable) { + } + + @Override + public void reportSuccessfulUnlockAttempt() { + } + + @Override + public void reportFailedUnlockAttempt() { + } + + @Override + public boolean isVerifyUnlockOnly() { + return false; + } + + @Override + public int getFailedAttempts() { + return 0; + } + + @Override + public void dismiss(boolean securityVerified) { + } + }; + @Override public void reset() { mIsVerifyUnlockOnly = false; @@ -566,10 +607,11 @@ public class KeyguardHostView extends KeyguardViewBase { break; } } - boolean simPukFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_full_screen); - if (view == null) { + boolean simPukFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen); + int layoutId = getLayoutIdFor(securityMode); + if (view == null && layoutId != 0) { final LayoutInflater inflater = LayoutInflater.from(mContext); - View v = inflater.inflate(getLayoutIdFor(securityMode), this, false); + View v = inflater.inflate(layoutId, this, false); mSecurityViewContainer.addView(v); updateSecurityView(v); @@ -585,7 +627,8 @@ public class KeyguardHostView extends KeyguardViewBase { } } - if (securityMode == SecurityMode.SimPin || securityMode == SecurityMode.SimPuk) { + if (securityMode == SecurityMode.SimPin || securityMode == SecurityMode.SimPuk || + securityMode == SecurityMode.Account) { if (simPukFullScreen) { mAppWidgetRegion.setVisibility(View.GONE); } @@ -596,7 +639,7 @@ public class KeyguardHostView extends KeyguardViewBase { View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container); selectorView.setCarrierArea(carrierText); } - + return view; } @@ -607,16 +650,20 @@ public class KeyguardHostView extends KeyguardViewBase { * @param securityMode */ private void showSecurityScreen(SecurityMode securityMode) { - if (DEBUG) Log.d(TAG, "showSecurityScreen"); - + if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")"); + if (securityMode == mCurrentSecuritySelection) return; KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection); KeyguardSecurityView newView = getSecurityView(securityMode); // Emulate Activity life cycle - oldView.onPause(); + if (oldView != null) { + oldView.onPause(); + oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view + } newView.onResume(); + newView.setKeyguardCallback(mCallback); final boolean needsInput = newView.needsInput(); if (mViewMediatorCallback != null) { @@ -627,10 +674,12 @@ public class KeyguardHostView extends KeyguardViewBase { final int childCount = mSecurityViewContainer.getChildCount(); // Do flip animation to the next screen - mSecurityViewContainer.setInAnimation( - AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_in)); - mSecurityViewContainer.setOutAnimation( - AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_out)); + if (false) { + mSecurityViewContainer.setInAnimation( + AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_in)); + mSecurityViewContainer.setOutAnimation( + AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_animate_out)); + } final int securityViewIdForMode = getSecurityViewIdForMode(securityMode); for (int i = 0; i < childCount; i++) { if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) { @@ -639,15 +688,10 @@ public class KeyguardHostView extends KeyguardViewBase { } } - if (securityMode == SecurityMode.None) { // Discard current runnable if we're switching back to the selector view setOnDismissRunnable(null); - setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK); - } else { - setSystemUiVisibility(getSystemUiVisibility() & (~View.STATUS_BAR_DISABLE_BACK)); } - mCurrentSecuritySelection = securityMode; } @@ -750,7 +794,7 @@ public class KeyguardHostView extends KeyguardViewBase { case SimPin: return R.layout.keyguard_sim_pin_view; case SimPuk: return R.layout.keyguard_sim_puk_view; default: - throw new RuntimeException("No layout for securityMode " + securityMode); + return 0; } } @@ -787,17 +831,12 @@ public class KeyguardHostView extends KeyguardViewBase { public void onListenerDetached() { int page = getWidgetPosition(R.id.keyguard_transport_control); if (page != -1) { - if (page == mAppWidgetContainer.getCurrentPage()) { - // Switch back to clock view if music was showing. - mAppWidgetContainer - .setCurrentPage(getWidgetPosition(R.id.keyguard_status_view)); - } mAppWidgetContainer.removeView(mTransportControl); - // XXX keep view attached to hierarchy so we still get show/hide events - // from AudioManager + // XXX keep view attached so we still get show/hide events from AudioManager KeyguardHostView.this.addView(mTransportControl); mTransportControl.setVisibility(View.GONE); mTransportState = TRANSPORT_GONE; + mTransportControl.post(mSwitchPageRunnable); } } @@ -817,7 +856,7 @@ public class KeyguardHostView extends KeyguardViewBase { }); } - mKeyguardStatusViewManager = ((KeyguardStatusView) + mKeyguardStatusViewManager = ((KeyguardStatusView) findViewById(R.id.keyguard_status_view_face_palm)).getManager(); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java index 74b244d..cec2668 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardNavigationManager.java @@ -16,26 +16,27 @@ package com.android.internal.policy.impl.keyguard; -import android.view.View; import android.widget.TextView; -import com.android.internal.R; - public class KeyguardNavigationManager implements SecurityMessageDisplay { private TextView mMessageArea; public KeyguardNavigationManager(TextView messageArea) { - mMessageArea = messageArea; - mMessageArea.setSelected(true); // Make marquee work + if (messageArea != null) { + mMessageArea = messageArea; + mMessageArea.setSelected(true); // Make marquee work + } } - public void setMessage(CharSequence msg) { + public void setMessage(CharSequence msg, boolean important) { + if (mMessageArea == null) return; mMessageArea.setText(msg); mMessageArea.announceForAccessibility(mMessageArea.getText()); } - public void setMessage(int resId) { + public void setMessage(int resId, boolean important) { + if (mMessageArea == null) return; if (resId != 0) { mMessageArea.setText(resId); mMessageArea.announceForAccessibility(mMessageArea.getText()); @@ -44,7 +45,8 @@ public class KeyguardNavigationManager implements SecurityMessageDisplay { } } - public void setMessage(int resId, Object... formatArgs) { + public void setMessage(int resId, boolean important, Object... formatArgs) { + if (mMessageArea == null) return; if (resId != 0) { mMessageArea.setText(mMessageArea.getContext().getString(resId, formatArgs)); mMessageArea.announceForAccessibility(mMessageArea.getText()); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java index 5a1c30f..1868507 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java @@ -86,6 +86,13 @@ public class KeyguardPasswordView extends LinearLayout mLockPatternUtils = utils; } + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + if (hasWindowFocus) { + reset(); + } + } + public void reset() { // start fresh mPasswordEntry.setText(""); @@ -102,13 +109,16 @@ public class KeyguardPasswordView extends LinearLayout private void resetState() { mSecurityMessageDisplay.setMessage( - mIsAlpha ? R.string.kg_password_instructions : R.string.kg_pin_instructions); + mIsAlpha ? R.string.kg_password_instructions : R.string.kg_pin_instructions, false); mPasswordEntry.setEnabled(true); mKeyboardView.setEnabled(true); } @Override protected void onFinishInflate() { + // We always set a dummy NavigationManager to avoid null checks + mSecurityMessageDisplay = new KeyguardNavigationManager(null); + mLockPatternUtils = new LockPatternUtils(mContext); // TODO: use common one final int quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(); @@ -188,7 +198,9 @@ public class KeyguardPasswordView extends LinearLayout } public void afterTextChanged(Editable s) { - mCallback.userActivity(0); + if (mCallback != null) { + mCallback.userActivity(0); + } } }); @@ -207,12 +219,13 @@ public class KeyguardPasswordView extends LinearLayout }); } - // If no icon is visible, reset the left margin on the password field so the text is + // If no icon is visible, reset the start margin on the password field so the text is // still centered. if (!imeOrDeleteButtonVisible) { android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); if (params instanceof MarginLayoutParams) { - ((MarginLayoutParams)params).leftMargin = 0; + final MarginLayoutParams mlp = (MarginLayoutParams) params; + mlp.setMarginStart(0); mPasswordEntry.setLayoutParams(params); } } @@ -287,7 +300,7 @@ public class KeyguardPasswordView extends LinearLayout handleAttemptLockout(deadline); } mSecurityMessageDisplay.setMessage( - mIsAlpha ? R.string.kg_wrong_password : R.string.kg_wrong_pin); + mIsAlpha ? R.string.kg_wrong_password : R.string.kg_wrong_pin, true); } mPasswordEntry.setText(""); } @@ -303,7 +316,7 @@ public class KeyguardPasswordView extends LinearLayout public void onTick(long millisUntilFinished) { int secondsRemaining = (int) (millisUntilFinished / 1000); mSecurityMessageDisplay.setMessage( - R.string.kg_too_many_failed_attempts_countdown, secondsRemaining); + R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining); } @Override @@ -365,10 +378,10 @@ public class KeyguardPasswordView extends LinearLayout public void afterTextChanged(Editable s) { } - @Override public void setSecurityMessageDisplay(SecurityMessageDisplay display) { - mSecurityMessageDisplay = display; + mSecurityMessageDisplay = display; + reset(); } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java index d8d7990..dcf40bf 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java @@ -111,6 +111,9 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit protected void onFinishInflate() { super.onFinishInflate(); + // We always set a dummy NavigationManager to avoid null checks + mSecurityMessageDisplay = new KeyguardNavigationManager(null); + mLockPatternUtils = mLockPatternUtils == null ? new LockPatternUtils(mContext) : mLockPatternUtils; @@ -182,7 +185,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit if (deadline != 0) { handleAttemptLockout(deadline); } else { - mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions); + mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false); } // the footer depends on how many total attempts the user has failed @@ -254,7 +257,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); handleAttemptLockout(deadline); } else { - mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern); + mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true); mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS); } } @@ -281,8 +284,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit private void next() { // if we are ready to enable the fallback or if we depleted the list of accounts // then finish and get out - if (mAccountIndex >= mAccounts.length) { - mEnableFallback = true; + if (mEnableFallback || mAccountIndex >= mAccounts.length) { return; } @@ -319,7 +321,9 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit mLockPatternView.clearPattern(); mLockPatternView.setEnabled(false); final long elapsedRealtime = SystemClock.elapsedRealtime(); - updateFooter(FooterMode.ForgotLockPattern); + if (mEnableFallback) { + updateFooter(FooterMode.ForgotLockPattern); + } mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) { @@ -327,13 +331,13 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit public void onTick(long millisUntilFinished) { final int secondsRemaining = (int) (millisUntilFinished / 1000); mSecurityMessageDisplay.setMessage( - R.string.kg_too_many_failed_attempts_countdown, secondsRemaining); + R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining); } @Override public void onFinish() { mLockPatternView.setEnabled(true); - mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions); + mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false); // TODO mUnlockIcon.setVisibility(View.VISIBLE); mFailedPatternAttemptsSinceLastTimeout = 0; if (mEnableFallback) { @@ -371,7 +375,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit @Override public void setSecurityMessageDisplay(SecurityMessageDisplay display) { - mSecurityMessageDisplay = display; + mSecurityMessageDisplay = display; + reset(); } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java index 80282c1..59e2ca9 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java @@ -28,6 +28,7 @@ public class KeyguardSecurityModel { * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode() */ enum SecurityMode { + Invalid, // NULL state None, // No security enabled Pattern, // Unlock by drawing a pattern. Password, // Unlock by entering a password or PIN @@ -53,7 +54,7 @@ public class KeyguardSecurityModel { * Returns true if biometric unlock is installed and selected. If this returns false there is * no need to even construct the biometric unlock. */ - private boolean isBiometricUnlockEnabled() { + boolean isBiometricUnlockEnabled() { return mLockPatternUtils.usingBiometricWeak() && mLockPatternUtils.isBiometricWeakInstalled(); } @@ -128,15 +129,7 @@ public class KeyguardSecurityModel { * * @return backup method or current security mode */ - SecurityMode getBackupSecurityMode() { - SecurityMode mode = getSecurityMode(); - - // Note that getAlternateFor() cannot be called here because we want to get the backup for - // biometric unlock even if it's suppressed; it just has to be enabled. - if (isBiometricUnlockEnabled() - && (mode == SecurityMode.Password || mode == SecurityMode.Pattern)) { - mode = SecurityMode.Biometric; - } + SecurityMode getBackupSecurityMode(SecurityMode mode) { switch(mode) { case Biometric: return getSecurityMode(); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java index 3516af9..7878e46 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java @@ -76,6 +76,9 @@ public class KeyguardSimPinView extends LinearLayout protected void onFinishInflate() { super.onFinishInflate(); + // We always set a dummy NavigationManager to avoid null checks + mSecurityMessageDisplay = new KeyguardNavigationManager(null); + mPinEntry = (EditText) findViewById(R.id.sim_pin_entry); mPinEntry.setOnEditorActionListener(this); mPinEntry.addTextChangedListener(this); @@ -110,9 +113,7 @@ public class KeyguardSimPinView extends LinearLayout public void reset() { // start fresh - if (mSecurityMessageDisplay != null) { - mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions); - } + mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true); // make sure that the number of entered digits is consistent when we // erase the SIM unlock code, including orientation changes. @@ -193,7 +194,7 @@ public class KeyguardSimPinView extends LinearLayout private void checkPin() { if (mPinEntry.getText().length() < 4) { // otherwise, display a message to the user, and don't submit. - mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint); + mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true); mPinEntry.setText(""); mCallback.userActivity(0); return; @@ -216,7 +217,8 @@ public class KeyguardSimPinView extends LinearLayout KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(); mCallback.dismiss(true); } else { - mSecurityMessageDisplay.setMessage(R.string.kg_password_wrong_pin_code); + mSecurityMessageDisplay.setMessage + (R.string.kg_password_wrong_pin_code, true); mPinEntry.setText(""); } mCallback.userActivity(0); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java index 2194c80..562d893 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java @@ -91,7 +91,7 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList } else if (state == CONFIRM_PIN) { if (confirmPin()) { state = DONE; - msg = R.string.kg_login_checking_password; + msg = R.string.lockscreen_sim_unlock_progress_dialog_message; updateSim(); } else { msg = R.string.kg_invalid_confirm_pin_hint; @@ -99,7 +99,7 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList } mSimPinEntry.setText(null); if (msg != 0) { - mSecurityMessageDisplay.setMessage(msg); + mSecurityMessageDisplay.setMessage(msg, true); } } @@ -107,9 +107,7 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList mPinText=""; mPukText=""; state = ENTER_PUK; - if (mSecurityMessageDisplay != null) { - mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint); - } + mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint, true); mSimPinEntry.requestFocus(); } } @@ -132,6 +130,9 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList protected void onFinishInflate() { super.onFinishInflate(); + // We always set a dummy NavigationManager to avoid null checks + mSecurityMessageDisplay = new KeyguardNavigationManager(null); + mSimPinEntry = (TextView) findViewById(R.id.sim_pin_entry); mSimPinEntry.setOnEditorActionListener(this); mSimPinEntry.addTextChangedListener(this); @@ -279,7 +280,7 @@ public class KeyguardSimPukView extends LinearLayout implements View.OnClickList mCallback.dismiss(true); } else { mStateMachine.reset(); - mSecurityMessageDisplay.setMessage(R.string.kg_invalid_puk); + mSecurityMessageDisplay.setMessage(R.string.kg_invalid_puk, true); } mCheckInProgress = false; } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java index ab2e170..5b85064 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java @@ -188,13 +188,17 @@ class KeyguardStatusViewManager implements SecurityMessageDisplay { updateStatusLines(); } - public void setMessage(CharSequence msg) { - mSecurityMessageContents = msg; + public void setMessage(CharSequence msg, boolean important) { + if (!important) { + mSecurityMessageContents = ""; + } else { + mSecurityMessageContents = msg; + } securityMessageChanged(); } - public void setMessage(int resId) { - if (resId != 0) { + public void setMessage(int resId, boolean important) { + if (resId != 0 && important) { mSecurityMessageContents = getContext().getResources().getText(resId); } else { mSecurityMessageContents = ""; @@ -202,8 +206,8 @@ class KeyguardStatusViewManager implements SecurityMessageDisplay { securityMessageChanged(); } - public void setMessage(int resId, Object... formatArgs) { - if (resId != 0) { + public void setMessage(int resId, boolean important, Object... formatArgs) { + if (resId != 0 && important) { mSecurityMessageContents = getContext().getString(resId, formatArgs); } else { mSecurityMessageContents = ""; @@ -217,6 +221,7 @@ class KeyguardStatusViewManager implements SecurityMessageDisplay { mHandler.removeCallbacks(mClearSecurityMessageRunnable); mHandler.postDelayed(mClearSecurityMessageRunnable, SECURITY_MESSAGE_DURATION); } + mSecurityMessage.announceForAccessibility(mSecurityMessage.getText()); } /** 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 1ec4176..0ad2404 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java @@ -210,6 +210,18 @@ public class KeyguardViewManager { mKeyguardView.setLockPatternUtils(mLockPatternUtils); mKeyguardView.setViewMediatorCallback(mViewMediatorCallback); + // HACK + // The keyguard view will have set up window flags in onFinishInflate before we set + // the view mediator callback. Make sure it knows the correct IME state. + if (mViewMediatorCallback != null) { + KeyguardPasswordView kpv = (KeyguardPasswordView) mKeyguardView.findViewById( + R.id.keyguard_password_view); + + if (kpv != null) { + mViewMediatorCallback.setNeedsInput(kpv.needsInput()); + } + } + if (options != null) { if (options.getBoolean(LockPatternUtils.KEYGUARD_SHOW_USER_SWITCHER)) { mKeyguardView.goToUserSwitcher(); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetRegion.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetRegion.java index bd79d67..4ff6f27 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetRegion.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetRegion.java @@ -29,6 +29,9 @@ public class KeyguardWidgetRegion extends LinearLayout implements PagedView.Page private int mPage = 0; private Callbacks mCallbacks; + // We are disabling touch interaction of the widget region for factory ROM. + private static final boolean DISABLE_TOUCH_INTERACTION = true; + private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000; public KeyguardWidgetRegion(Context context) { @@ -52,19 +55,21 @@ public class KeyguardWidgetRegion extends LinearLayout implements PagedView.Page mPager.setPageSwitchListener(this); setSoundEffectsEnabled(false); - setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - showPagingFeedback(); - } - }); + if (!DISABLE_TOUCH_INTERACTION) { + setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + showPagingFeedback(); + } + }); + } } public void showPagingFeedback() { - if (true || (mPage < mPager.getPageCount() - 1)) { + if ((mPage < mPager.getPageCount() - 1)) { mLeftStrip.makeEmGo(); } - if (true || (mPage > 0)) { + if ((mPage > 0)) { mRightStrip.makeEmGo(); } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java index d834741..86c05b1 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java @@ -77,6 +77,9 @@ public class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeL private static final int MIN_SNAP_VELOCITY = 1500; private static final int MIN_FLING_VELOCITY = 250; + // We are disabling touch interaction of the widget region for factory ROM. + private static final boolean DISABLE_TOUCH_INTERACTION = true; + static final int AUTOMATIC_PAGE_SPACING = -1; protected int mFlingThresholdVelocity; @@ -317,6 +320,7 @@ public class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeL return; } + mForceScreenScrolled = true; mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1)); updateCurrentPageScroll(); updateScrollingIndicator(); @@ -861,6 +865,10 @@ public class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeL @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (DISABLE_TOUCH_INTERACTION) { + return false; + } + /* * This method JUST determines whether we want to intercept the motion. * If we return true, onTouchEvent will be called and we do the actual @@ -1099,6 +1107,10 @@ public class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeL @Override public boolean onTouchEvent(MotionEvent ev) { + if (DISABLE_TOUCH_INTERACTION) { + return false; + } + // Skip touch handling if there are no pages to swipe if (getChildCount() <= 0) return super.onTouchEvent(ev); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java b/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java index 98fd11e..b57d8c1 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java @@ -17,9 +17,9 @@ package com.android.internal.policy.impl.keyguard; public interface SecurityMessageDisplay { - public void setMessage(CharSequence msg); + public void setMessage(CharSequence msg, boolean important); - public void setMessage(int resId); + public void setMessage(int resId, boolean important); - public void setMessage(int resId, Object... formatArgs); + public void setMessage(int resId, boolean important, Object... formatArgs); } diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index c18fe0e..e7e4f87 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -304,6 +304,8 @@ class AppWidgetService extends IAppWidgetService.Stub @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); + // Dump the state of all the app widget providers synchronized (mAppWidgetServices) { IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index c5016e6..6948927 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -609,10 +609,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } /** - * Throw SecurityException if caller has neither COARSE or FINE. - * Otherwise, return the best permission. + * Returns the best permission available to the caller. */ - private String checkPermission() { + private String getBestCallingPermission() { if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { return ACCESS_FINE_LOCATION; @@ -620,9 +619,20 @@ public class LocationManagerService extends ILocationManager.Stub implements Run PackageManager.PERMISSION_GRANTED) { return ACCESS_COARSE_LOCATION; } + return null; + } - throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" + - " ACCESS_FINE_LOCATION permission"); + /** + * Throw SecurityException if caller has neither COARSE or FINE. + * Otherwise, return the best permission. + */ + private String checkPermission() { + String perm = getBestCallingPermission(); + if (perm == null) { + throw new SecurityException("Location requires either ACCESS_COARSE_LOCATION or" + + " ACCESS_FINE_LOCATION permission"); + } + return perm; } /** @@ -635,19 +645,15 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - private boolean isAllowedProviderSafe(String provider) { + private String getMinimumPermissionForProvider(String provider) { if (LocationManager.GPS_PROVIDER.equals(provider) || LocationManager.PASSIVE_PROVIDER.equals(provider)) { // gps and passive providers require FINE permission - return mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) - == PackageManager.PERMISSION_GRANTED; + return ACCESS_FINE_LOCATION; } else if (LocationManager.NETWORK_PROVIDER.equals(provider) || LocationManager.FUSED_PROVIDER.equals(provider)) { // network and fused providers are ok with COARSE or FINE - return (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) - == PackageManager.PERMISSION_GRANTED) || - (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) - == PackageManager.PERMISSION_GRANTED); + return ACCESS_COARSE_LOCATION; } else { // mock providers LocationProviderInterface lp = mMockProviders.get(provider); @@ -656,20 +662,43 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (properties != null) { if (properties.mRequiresSatellite) { // provider requiring satellites require FINE permission - return mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) - == PackageManager.PERMISSION_GRANTED; + return ACCESS_FINE_LOCATION; } else if (properties.mRequiresNetwork || properties.mRequiresCell) { // provider requiring network and or cell require COARSE or FINE - return (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) - == PackageManager.PERMISSION_GRANTED) || - (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) - == PackageManager.PERMISSION_GRANTED); + return ACCESS_COARSE_LOCATION; } } } } - return false; + return null; + } + + private boolean isPermissionSufficient(String perm, String minPerm) { + if (ACCESS_FINE_LOCATION.equals(minPerm)) { + return ACCESS_FINE_LOCATION.equals(perm); + } else if (ACCESS_COARSE_LOCATION.equals(minPerm)) { + return ACCESS_FINE_LOCATION.equals(perm) || + ACCESS_COARSE_LOCATION.equals(perm); + } else { + return false; + } + } + + private void checkPermissionForProvider(String perm, String provider) { + String minPerm = getMinimumPermissionForProvider(provider); + if (!isPermissionSufficient(perm, minPerm)) { + if (ACCESS_FINE_LOCATION.equals(minPerm)) { + throw new SecurityException("Location provider \"" + provider + + "\" requires ACCESS_FINE_LOCATION permission."); + } else if (ACCESS_COARSE_LOCATION.equals(minPerm)) { + throw new SecurityException("Location provider \"" + provider + + "\" requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission."); + } else { + throw new SecurityException("Insufficient permission for location provider \"" + + provider + "\"."); + } + } } /** @@ -703,6 +732,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public List<String> getProviders(Criteria criteria, boolean enabledOnly) { ArrayList<String> out; + String perm = getBestCallingPermission(); int callingUserId = UserHandle.getCallingUserId(); long identity = Binder.clearCallingIdentity(); try { @@ -713,7 +743,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (LocationManager.FUSED_PROVIDER.equals(name)) { continue; } - if (isAllowedProviderSafe(name)) { + if (isPermissionSufficient(perm, getMinimumPermissionForProvider(name))) { if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) { continue; } @@ -980,26 +1010,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run return receiver; } - private boolean isProviderAllowedByCoarsePermission(String provider) { - if (LocationManager.FUSED_PROVIDER.equals(provider)) { - return true; - } - if (LocationManager.PASSIVE_PROVIDER.equals(provider)) { - return true; - } - if (LocationManager.NETWORK_PROVIDER.equals(provider)) { - return true; - } - return false; - } - private String checkPermissionAndRequest(LocationRequest request) { - String perm = checkPermission(); + String perm = getBestCallingPermission(); + String provider = request.getProvider(); + checkPermissionForProvider(perm, provider); if (ACCESS_COARSE_LOCATION.equals(perm)) { - if (!isProviderAllowedByCoarsePermission(request.getProvider())) { - throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); - } switch (request.getQuality()) { case LocationRequest.ACCURACY_FINE: request.setQuality(LocationRequest.ACCURACY_BLOCK); @@ -1324,7 +1340,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run */ @Override public ProviderProperties getProviderProperties(String provider) { - checkPermission(); + checkPermissionForProvider(getBestCallingPermission(), provider); LocationProviderInterface p; synchronized (mLock) { @@ -1337,13 +1353,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public boolean isProviderEnabled(String provider) { - String perms = checkPermission(); + checkPermissionForProvider(getBestCallingPermission(), provider); if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; - if (ACCESS_COARSE_LOCATION.equals(perms) && - !isProviderAllowedByCoarsePermission(provider)) { - throw new SecurityException("The \"" + provider + - "\" provider requires ACCESS_FINE_LOCATION permission"); - } long identity = Binder.clearCallingIdentity(); try { diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index 03ff21f..bb19cc7 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -628,6 +628,7 @@ public class Vpn extends BaseNetworkStateTracker { private final String[] mDaemons; private final String[][] mArguments; private final LocalSocket[] mSockets; + private final String mOuterInterface; private long mTimer = -1; @@ -638,10 +639,15 @@ public class Vpn extends BaseNetworkStateTracker { // TODO: clear arguments from memory once launched mArguments = new String[][] {racoon, mtpd}; mSockets = new LocalSocket[mDaemons.length]; + + // This is the interface which VPN is running on, + // mConfig.interfaze will change to point to OUR + // internal interface soon. TODO - add inner/outer to mconfig + mOuterInterface = mConfig.interfaze; } public void check(String interfaze) { - if (interfaze.equals(mConfig.interfaze)) { + if (interfaze.equals(mOuterInterface)) { Log.i(TAG, "Legacy VPN is going down with " + interfaze); exit(); } diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index 3e541dd..c441b02 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -198,6 +198,12 @@ final class WifiDisplayAdapter extends DisplayAdapter { updateRememberedDisplaysLocked(); scheduleStatusChangedBroadcastLocked(); } + + if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address) + && mDisplayDevice != null) { + mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName()); + sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED); + } } public void requestForgetLocked(String address) { @@ -397,7 +403,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { }; private final class WifiDisplayDevice extends DisplayDevice { - private final String mName; + private String mName; private final int mWidth; private final int mHeight; private final float mRefreshRate; @@ -423,6 +429,11 @@ final class WifiDisplayAdapter extends DisplayAdapter { sendTraversalRequestLocked(); } + public void setNameLocked(String name) { + mName = name; + mInfo = null; + } + @Override public void performTraversalInTransactionLocked() { setSurfaceInTransactionLocked(mSurface); diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java index b76ad45..4e692a2 100644 --- a/services/java/com/android/server/power/PowerManagerService.java +++ b/services/java/com/android/server/power/PowerManagerService.java @@ -162,6 +162,11 @@ public final class PowerManagerService extends IPowerManager.Stub // Poll interval in milliseconds for watching boot animation finished. private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; + // If the battery level drops by this percentage and the user activity timeout + // has expired, then assume the device is receiving insufficient current to charge + // effectively and terminate the dream. + private static final int DREAM_BATTERY_LEVEL_DRAIN_CUTOFF = 5; + private Context mContext; private LightsService mLightsService; private BatteryService mBatteryService; @@ -256,6 +261,14 @@ public final class PowerManagerService extends IPowerManager.Stub // The current plug type, such as BatteryManager.BATTERY_PLUGGED_WIRELESS. private int mPlugType; + // The current battery level percentage. + private int mBatteryLevel; + + // The battery level percentage at the time the dream started. + // This is used to terminate a dream and go to sleep if the battery is + // draining faster than it is charging and the user activity timeout has expired. + private int mBatteryLevelWhenDreamStarted; + // True if the device should wake up when plugged or unplugged. private boolean mWakeUpWhenPluggedOrUnpluggedConfig; @@ -1067,12 +1080,14 @@ public final class PowerManagerService extends IPowerManager.Stub final int oldPlugType = mPlugType; mIsPowered = mBatteryService.isPowered(BatteryManager.BATTERY_PLUGGED_ANY); mPlugType = mBatteryService.getPlugType(); + mBatteryLevel = mBatteryService.getBatteryLevel(); if (DEBUG) { Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered + ", mIsPowered=" + mIsPowered + ", oldPlugType=" + oldPlugType - + ", mPlugType=" + mPlugType); + + ", mPlugType=" + mPlugType + + ", mBatteryLevel=" + mBatteryLevel); } if (wasPowered != mIsPowered || oldPlugType != mPlugType) { @@ -1126,8 +1141,7 @@ public final class PowerManagerService extends IPowerManager.Stub } if (!wasPowered && mIsPowered && mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS - && mBatteryService.getBatteryLevel() >= - WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) { + && mBatteryLevel >= WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT) { return false; } @@ -1403,7 +1417,7 @@ public final class PowerManagerService extends IPowerManager.Stub mSandmanScheduled = false; boolean canDream = canDreamLocked(); if (DEBUG_SPEW) { - Log.d(TAG, "handleSandman: canDream=" + canDream + Slog.d(TAG, "handleSandman: canDream=" + canDream + ", mWakefulness=" + wakefulnessToString(mWakefulness)); } @@ -1431,10 +1445,24 @@ public final class PowerManagerService extends IPowerManager.Stub if (mWakefulness == WAKEFULNESS_NAPPING) { mWakefulness = WAKEFULNESS_DREAMING; mDirty |= DIRTY_WAKEFULNESS; + mBatteryLevelWhenDreamStarted = mBatteryLevel; updatePowerStateLocked(); continueDreaming = true; } else if (mWakefulness == WAKEFULNESS_DREAMING) { - continueDreaming = true; + if (!isBeingKeptAwakeLocked() + && mBatteryLevel < mBatteryLevelWhenDreamStarted + - DREAM_BATTERY_LEVEL_DRAIN_CUTOFF) { + // If the user activity timeout expired and the battery appears + // to be draining faster than it is charging then stop dreaming + // and go to sleep. + Slog.i(TAG, "Stopping dream because the battery appears to " + + "be draining faster than it is charging. " + + "Battery level when dream started: " + + mBatteryLevelWhenDreamStarted + "%. " + + "Battery level now: " + mBatteryLevel + "%."); + } else { + continueDreaming = true; + } } } if (!continueDreaming) { @@ -1704,8 +1732,11 @@ public final class PowerManagerService extends IPowerManager.Stub } /** - * Reboot the device, passing 'reason' (may be null) - * to the underlying __reboot system call. Should not return. + * Reboots the device. + * + * @param confirm If true, shows a reboot confirmation dialog. + * @param reason The reason for the reboot, or null if none. + * @param wait If true, this call waits for the reboot to complete and does not return. */ @Override // Binder call public void reboot(boolean confirm, String reason, boolean wait) { @@ -1713,15 +1744,17 @@ public final class PowerManagerService extends IPowerManager.Stub final long ident = Binder.clearCallingIdentity(); try { - rebootInternal(false, confirm, reason, wait); + shutdownOrRebootInternal(false, confirm, reason, wait); } finally { Binder.restoreCallingIdentity(ident); } } /** - * Shutdown the devic, passing 'reason' (may be null) - * to the underlying __reboot system call. Should not return. + * Shuts down the device. + * + * @param confirm If true, shows a shutdown confirmation dialog. + * @param wait If true, this call waits for the shutdown to complete and does not return. */ @Override // Binder call public void shutdown(boolean confirm, boolean wait) { @@ -1729,19 +1762,20 @@ public final class PowerManagerService extends IPowerManager.Stub final long ident = Binder.clearCallingIdentity(); try { - rebootInternal(true, confirm, null, wait); + shutdownOrRebootInternal(true, confirm, null, wait); } finally { Binder.restoreCallingIdentity(ident); } } - private void rebootInternal(final boolean shutdown, final boolean confirm, + private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm, final String reason, boolean wait) { if (mHandler == null || !mSystemReady) { - throw new IllegalStateException("Too early to call reboot()"); + throw new IllegalStateException("Too early to call shutdown() or reboot()"); } Runnable runnable = new Runnable() { + @Override public void run() { synchronized (this) { if (shutdown) { @@ -1789,6 +1823,7 @@ public final class PowerManagerService extends IPowerManager.Stub private void crashInternal(final String message) { Thread t = new Thread("PowerManagerService.crash()") { + @Override public void run() { throw new RuntimeException(message); } @@ -2087,6 +2122,8 @@ public final class PowerManagerService extends IPowerManager.Stub pw.println(" mWakefulness=" + wakefulnessToString(mWakefulness)); pw.println(" mIsPowered=" + mIsPowered); pw.println(" mPlugType=" + mPlugType); + pw.println(" mBatteryLevel=" + mBatteryLevel); + pw.println(" mBatteryLevelWhenDreamStarted=" + mBatteryLevelWhenDreamStarted); pw.println(" mStayOn=" + mStayOn); pw.println(" mProximityPositive=" + mProximityPositive); pw.println(" mBootCompleted=" + mBootCompleted); diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index b67fb51..269eac0 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -618,6 +618,7 @@ public class WindowAnimator { if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( TAG, ">>> OPEN TRANSACTION animateLocked"); Surface.openTransaction(); + Surface.setAnimationTransaction(); try { updateAppWindowsLocked(); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 77d815b..c341872 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -2823,16 +2823,9 @@ public class WindowManagerService extends IWindowManager.Stub "Relayout window turning screen on: " + win); win.mTurnOnScreen = true; } - int diff = 0; - if (win.mConfiguration != mCurConfiguration - && (win.mConfiguration == null - || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) { - win.mConfiguration = mCurConfiguration; - if (DEBUG_CONFIGURATION) { - Slog.i(TAG, "Window " + win + " visible with new config: " - + win.mConfiguration + " / 0x" - + Integer.toHexString(diff)); - } + if (win.isConfigChanged()) { + if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win + + " visible with new config: " + win.mConfiguration); outConfig.setTo(mCurConfiguration); } } @@ -8260,7 +8253,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.v(TAG, "1ST PASS " + win + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame + " mLayoutAttached=" + win.mLayoutAttached - + " screen changed=" + win.isConfigDiff(ActivityInfo.CONFIG_SCREEN_SIZE)); + + " screen changed=" + win.isConfigChanged()); final AppWindowToken atoken = win.mAppToken; if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + win.mViewVisibility + " mRelayoutCalled=" @@ -8282,7 +8275,7 @@ public class WindowManagerService extends IWindowManager.Stub // windows, since that means "perform layout as normal, // just don't display"). if (!gone || !win.mHaveFrame || win.mLayoutNeeded - || win.isConfigDiff(ActivityInfo.CONFIG_SCREEN_SIZE) + || win.isConfigChanged() || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { if (!win.mLayoutAttached) { if (initial) { diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java index 26cb97b..fd594f7 100644 --- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java +++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java @@ -66,7 +66,7 @@ public class SystemClock_Delegate { * @return elapsed nanoseconds since boot. */ @LayoutlibDelegate - /*package*/ static long elapsedRealtimeNano() { + /*package*/ static long elapsedRealtimeNanos() { return System.nanoTime() - sBootTimeNano; } diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java new file mode 100644 index 0000000..f75ee50 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.view; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +/** + * Delegate used to provide new implementation of a select few methods of {@link Choreographer} + * + * Through the layoutlib_create tool, the original methods of Choreographer have been + * replaced by calls to methods of the same name in this delegate class. + * + */ +public class Choreographer_Delegate { + + @LayoutlibDelegate + public static float getRefreshRate() { + return 60.f; + } +} diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java index 6ccdcb6..53dc821 100644 --- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java @@ -16,11 +16,8 @@ package android.view; -import com.android.layoutlib.bridge.android.BridgeWindowManager; -import com.android.layoutlib.bridge.impl.RenderAction; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import android.os.RemoteException; /** * Delegate used to provide new implementation of a select few methods of {@link Display} @@ -31,4 +28,9 @@ import android.os.RemoteException; */ public class Display_Delegate { + @LayoutlibDelegate + static void updateDisplayInfoLocked(Display theDisplay) { + // do nothing + } + } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 3fcc8ef..da736b7 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.layoutlib.bridge.android; +package android.view; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; @@ -28,7 +28,6 @@ import android.os.IRemoteCallback; import android.os.RemoteException; import android.util.DisplayMetrics; import android.view.Display; -import android.view.Display_Delegate; import android.view.Gravity; import android.view.IApplicationToken; import android.view.IDisplayContentChangeListener; @@ -45,16 +44,21 @@ import java.util.List; * Basic implementation of {@link IWindowManager} so that {@link Display} (and * {@link Display_Delegate}) can return a valid instance. */ -public class BridgeWindowManager implements IWindowManager { +public class IWindowManagerImpl implements IWindowManager { private final Configuration mConfig; private final DisplayMetrics mMetrics; private final int mRotation; + private final boolean mHasSystemNavBar; + private final boolean mHasNavigationBar; - public BridgeWindowManager(Configuration config, DisplayMetrics metrics, int rotation) { + public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation, + boolean hasSystemNavBar, boolean hasNavigationBar) { mConfig = config; mMetrics = metrics; mRotation = rotation; + mHasSystemNavBar = hasSystemNavBar; + mHasNavigationBar = hasNavigationBar; } // custom API. @@ -70,14 +74,18 @@ public class BridgeWindowManager implements IWindowManager { return mRotation; } - // ---- unused implementation of IWindowManager ---- + @Override + public boolean hasNavigationBar() { + return mHasNavigationBar; + } @Override public boolean hasSystemNavBar() throws RemoteException { - // TODO Auto-generated method stub - return false; + return mHasSystemNavBar; } + // ---- unused implementation of IWindowManager ---- + @Override public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4, boolean arg5) @@ -435,11 +443,6 @@ public class BridgeWindowManager implements IWindowManager { } @Override - public boolean hasNavigationBar() { - return false; // should this return something else? - } - - @Override public void lockNow(Bundle options) { // TODO Auto-generated method stub } diff --git a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java new file mode 100644 index 0000000..2606e55 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +/** + * Delegate used to provide new implementation of a select few methods of + * {@link WindowManagerGlobal} + * + * Through the layoutlib_create tool, the original methods of WindowManagerGlobal have been + * replaced by calls to methods of the same name in this delegate class. + * + */ +public class WindowManagerGlobal_Delegate { + + private static IWindowManager sService; + + @LayoutlibDelegate + public static IWindowManager getWindowManagerService() { + return sService; + } + + // ---- internal implementation stuff ---- + + public static void setWindowManagerService(IWindowManager service) { + sService = service; + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 80478ba..e2fced6 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -25,6 +25,7 @@ import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.StyleResourceValue; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.android.view.WindowManagerImpl; import com.android.layoutlib.bridge.impl.ParserFactory; import com.android.layoutlib.bridge.impl.Stack; import com.android.resources.ResourceType; @@ -68,9 +69,9 @@ import android.util.TypedValue; import android.view.BridgeInflater; import android.view.CompatibilityInfoHolder; import android.view.Display; -import android.view.Surface; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; import android.view.textservice.TextServicesManager; import java.io.File; @@ -98,7 +99,7 @@ public final class BridgeContext extends Context { private final Configuration mConfig; private final ApplicationInfo mApplicationInfo; private final IProjectCallback mProjectCallback; - private final BridgeWindowManager mIWindowManager; + private final WindowManager mWindowManager; private Resources.Theme mTheme; @@ -139,10 +140,10 @@ public final class BridgeContext extends Context { mRenderResources = renderResources; mConfig = config; - mIWindowManager = new BridgeWindowManager(mConfig, metrics, Surface.ROTATION_0); - mApplicationInfo = new ApplicationInfo(); mApplicationInfo.targetSdkVersion = targetSdkVersion; + + mWindowManager = new WindowManagerImpl(mMetrics); } /** @@ -198,14 +199,14 @@ public final class BridgeContext extends Context { return mRenderResources; } - public BridgeWindowManager getIWindowManager() { - return mIWindowManager; - } - public Map<String, String> getDefaultPropMap(Object key) { return mDefaultPropMaps.get(key); } + public Configuration getConfiguration() { + return mConfig; + } + /** * Adds a parser to the stack. * @param parser the parser to add. @@ -431,10 +432,8 @@ public final class BridgeContext extends Context { return TextServicesManager.getInstance(); } - // AutoCompleteTextView and MultiAutoCompleteTextView want a window - // service. We don't have any but it's not worth an exception. if (WINDOW_SERVICE.equals(service)) { - return null; + return mWindowManager; } // needed by SearchView diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java new file mode 100644 index 0000000..9a633bf --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.layoutlib.bridge.android.view; + +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.DisplayInfo; +import android.view.View; +import android.view.WindowManager; + +public class WindowManagerImpl implements WindowManager { + + private final DisplayMetrics mMetrics; + private final Display mDisplay; + + public WindowManagerImpl(DisplayMetrics metrics) { + mMetrics = metrics; + + DisplayInfo info = new DisplayInfo(); + info.logicalHeight = mMetrics.heightPixels; + info.logicalWidth = mMetrics.widthPixels; + mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info, null); + } + + @Override + public Display getDefaultDisplay() { + return mDisplay; + } + + + @Override + public void addView(View arg0, android.view.ViewGroup.LayoutParams arg1) { + // pass + } + + @Override + public void removeView(View arg0) { + // pass + } + + @Override + public void updateViewLayout(View arg0, android.view.ViewGroup.LayoutParams arg1) { + // pass + } + + + @Override + public void removeViewImmediate(View arg0) { + // pass + } +} 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 e93b41d..cc0f077 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 @@ -68,11 +68,15 @@ 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.Surface; import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.MarginLayoutParams; +import android.view.WindowManagerGlobal_Delegate; import android.widget.AbsListView; import android.widget.AbsSpinner; import android.widget.AdapterView; @@ -185,6 +189,14 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { findActionBar(resources, metrics); findSystemBar(resources, metrics); + // FIXME: find those out, and possibly add them to the render params + boolean hasSystemNavBar = true; + boolean hasNavigationBar = true; + IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), + metrics, Surface.ROTATION_0, + hasSystemNavBar, hasNavigationBar); + WindowManagerGlobal_Delegate.setWindowManagerService(iwm); + // build the inflater and parser. mInflater = new BridgeInflater(context, params.getProjectCallback()); context.setBridgeInflater(mInflater); diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index 5109810..80a1a60 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -110,11 +110,13 @@ public final class CreateInfo implements ICreateInfo { "android.os.Handler#sendMessageAtTime", "android.os.HandlerThread#run", "android.os.Build#getString", - "android.view.Display#getWindowManager", + "android.view.Choreographer#getRefreshRate", + "android.view.Display#updateDisplayInfoLocked", "android.view.LayoutInflater#rInflate", "android.view.LayoutInflater#parseInclude", "android.view.View#isInEditMode", "android.view.ViewRootImpl#isInTouchMode", + "android.view.WindowManagerGlobal#getWindowManagerService", "android.view.inputmethod.InputMethodManager#getInstance", "com.android.internal.util.XmlUtils#convertValueToInt", "com.android.internal.textservice.ITextServicesManager$Stub#asInterface", diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 75b8bcf..e913d10 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1274,6 +1274,7 @@ public class WifiManager { // This will cause all further async API calls on the WifiManager // to fail and throw an exception mAsyncChannel = null; + getLooper().quit(); break; /* ActionListeners grouped together */ case WifiManager.CONNECT_NETWORK_FAILED: @@ -1979,4 +1980,12 @@ public class WifiManager { mService.captivePortalCheckComplete(); } catch (RemoteException e) {} } + + protected void finalize() throws Throwable { + try { + mHandler.getLooper().quit(); + } finally { + super.finalize(); + } + } } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java index 2093bda..f14c305 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java @@ -114,6 +114,15 @@ public class WifiP2pDeviceList implements Parcelable { return mDevices.remove(device.deviceAddress) != null; } + /** Returns true if any device the list was removed @hide */ + public boolean remove(WifiP2pDeviceList list) { + boolean ret = false; + for (WifiP2pDevice d : list.mDevices.values()) { + if (remove(d)) ret = true; + } + return ret; + } + /** Get the list of devices */ public Collection<WifiP2pDevice> getDeviceList() { return Collections.unmodifiableCollection(mDevices.values()); diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index ca329e6..70baf13 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -355,6 +355,15 @@ public class WifiP2pService extends IWifiP2pManager.Stub { private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative); private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList(); + /* During a connection, supplicant can tell us that a device was lost. From a supplicant's + * perspective, the discovery stops during connection and it purges device since it does + * not get latest updates about the device without being in discovery state. + * + * From the framework perspective, the device is still there since we are connecting or + * connected to it. so we keep these devices in a seperate list, so that they are removed + * when connection is cancelled or lost + */ + private final WifiP2pDeviceList mPeersLostDuringConnection = new WifiP2pDeviceList(); private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null, new GroupDeleteListener() { @Override @@ -746,6 +755,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub { public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { + case WifiMonitor.SUP_DISCONNECTION_EVENT: + loge("Unexpected loss of p2p socket connection"); + transitionTo(mP2pDisabledState); + break; case WifiStateMachine.CMD_ENABLE_P2P: //Nothing to do break; @@ -1066,7 +1079,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { break; } // Do nothing - if (DBG) logd("Retain connecting device " + device); + if (DBG) logd("Add device to lost list " + device); + mPeersLostDuringConnection.update(device); break; case WifiP2pManager.DISCOVER_PEERS: /* Discovery will break negotiation */ @@ -1401,7 +1415,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { device = (WifiP2pDevice) message.obj; //Device loss for a connected device indicates it is not in discovery any more if (mGroup.contains(device)) { - if (DBG) logd("Lost " + device +" , do nothing"); + if (DBG) logd("Add device to lost list " + device); + mPeersLostDuringConnection.update(device); return HANDLED; } // Do the regular device lost handling @@ -1853,7 +1868,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { private int connect(WifiP2pConfig config, boolean tryInvocation) { if (config == null) { - loge("invalid argument."); + loge("config is null"); return CONNECT_FAILURE; } @@ -1863,7 +1878,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { WifiP2pDevice dev = mPeers.get(config.deviceAddress); if (dev == null) { - loge("target device is not found."); + loge("target device not found " + config.deviceAddress); return CONNECT_FAILURE; } @@ -2142,6 +2157,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { /* After cancelling group formation, new connections on existing peers can fail * at supplicant. Flush and restart discovery */ mWifiNative.p2pFlush(); + if (mPeers.remove(mPeersLostDuringConnection)) sendP2pPeersChangedBroadcast(); + mPeersLostDuringConnection.clear(); mServiceDiscReqId = null; sendMessage(WifiP2pManager.DISCOVER_PEERS); } @@ -2174,6 +2191,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { mGroup = null; mWifiNative.p2pFlush(); + if (mPeers.remove(mPeersLostDuringConnection)) sendP2pPeersChangedBroadcast(); + mPeersLostDuringConnection.clear(); mServiceDiscReqId = null; if (changed) sendP2pPeersChangedBroadcast(); } |
