diff options
39 files changed, 646 insertions, 244 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 7260d1027660..9968dbbee3ec 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -89,7 +89,7 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; -import android.view.PhoneWindow; +import com.android.internal.policy.PhoneWindow; import android.view.SearchEvent; import android.view.View; import android.view.View.OnCreateContextMenuListener; diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index d04910417d65..f6e0e1e721b9 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -48,7 +48,7 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; -import android.view.PhoneWindow; +import com.android.internal.policy.PhoneWindow; import android.view.SearchEvent; import android.view.View; import android.view.View.OnCreateContextMenuListener; diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 46da025e8ec2..391131ac011f 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -91,7 +91,6 @@ import android.os.IPowerManager; import android.os.IUserManager; import android.os.PowerManager; import android.os.Process; -import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemVibrator; import android.os.UserHandle; @@ -111,7 +110,7 @@ import android.telephony.TelephonyManager; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; -import android.view.PhoneLayoutInflater; +import com.android.internal.policy.PhoneLayoutInflater; import android.view.WindowManager; import android.view.WindowManagerImpl; import android.view.accessibility.AccessibilityManager; diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 29aaf307cb14..01718694e811 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -40,7 +40,7 @@ import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; -import android.view.PhoneWindow; +import com.android.internal.policy.PhoneWindow; import android.view.SearchEvent; import android.view.View; import android.view.ViewGroup; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index fda6e6394fab..c9c2a8273054 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -76,6 +76,7 @@ import android.widget.Scroller; import com.android.internal.R; import com.android.internal.os.SomeArgs; +import com.android.internal.policy.PhoneFallbackEventHandler; import com.android.internal.util.ScreenShapeHelper; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 040fd371cb02..78604bfa294c 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -247,13 +247,6 @@ public final class InputMethodManager { /** @hide */ public static final int DISPATCH_HANDLED = 1; - /** @hide */ - public static final int SHOW_IM_PICKER_MODE_AUTO = 0; - /** @hide */ - public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1; - /** @hide */ - public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2; - final IInputMethodManager mService; final Looper mMainLooper; @@ -1897,28 +1890,9 @@ public final class InputMethodManager { } } - /** - * Shows the input method chooser dialog. - * - * @param showAuxiliarySubtypes Set true to show auxiliary input methods. - * @hide - */ - public void showInputMethodPicker(boolean showAuxiliarySubtypes) { - synchronized (mH) { - try { - final int mode = showAuxiliarySubtypes ? - SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES: - SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES; - mService.showInputMethodPickerFromClient(mClient, mode); - } catch (RemoteException e) { - Log.w(TAG, "IME died: " + mCurId, e); - } - } - } - private void showInputMethodPickerLocked() { try { - mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO); + mService.showInputMethodPickerFromClient(mClient); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 8d8b3a3bd297..97348e3089cf 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -28,7 +28,7 @@ import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.PhoneWindow; +import com.android.internal.policy.PhoneWindow; import android.view.View; import android.view.ViewGroup; import android.view.Window; diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java index ce94727cd9f5..52485ddb7fa7 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java +++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java @@ -196,7 +196,7 @@ public class InputMethodSubtypeSwitchingController { } public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList( - boolean showSubtypes, boolean includeAuxiliarySubtypes, boolean isScreenLocked) { + boolean showSubtypes, boolean inputShown, boolean isScreenLocked) { final ArrayList<ImeSubtypeListItem> imList = new ArrayList<ImeSubtypeListItem>(); final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis = @@ -205,12 +205,6 @@ public class InputMethodSubtypeSwitchingController { if (immis == null || immis.size() == 0) { return Collections.emptyList(); } - if (isScreenLocked && includeAuxiliarySubtypes) { - if (DEBUG) { - Slog.w(TAG, "Auxiliary subtypes are not allowed to be shown in lock screen."); - } - includeAuxiliarySubtypes = false; - } mSortedImmis.clear(); mSortedImmis.putAll(immis); for (InputMethodInfo imi : mSortedImmis.keySet()) { @@ -233,7 +227,7 @@ public class InputMethodSubtypeSwitchingController { final String subtypeHashCode = String.valueOf(subtype.hashCode()); // We show all enabled IMEs and subtypes when an IME is shown. if (enabledSubtypeSet.contains(subtypeHashCode) - && (includeAuxiliarySubtypes || !subtype.isAuxiliary())) { + && ((inputShown && !isScreenLocked) || !subtype.isAuxiliary())) { final CharSequence subtypeLabel = subtype.overridesImplicitlyEnabledSubtype() ? null : subtype .getDisplayName(mContext, imi.getPackageName(), @@ -522,8 +516,8 @@ public class InputMethodSubtypeSwitchingController { } public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked(boolean showSubtypes, - boolean includingAuxiliarySubtypes, boolean isScreenLocked) { + boolean inputShown, boolean isScreenLocked) { return mSubtypeList.getSortedInputMethodAndSubtypeList( - showSubtypes, includingAuxiliarySubtypes, isScreenLocked); + showSubtypes, inputShown, isScreenLocked); } } diff --git a/core/java/android/view/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java index 350650dfaa9e..2cb9c250d2d1 100644 --- a/core/java/android/view/PhoneFallbackEventHandler.java +++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.view; +package com.android.internal.policy; import android.app.KeyguardManager; import android.app.SearchManager; @@ -28,10 +28,11 @@ import android.os.UserHandle; import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.Log; -import android.view.View; -import android.view.HapticFeedbackConstants; import android.view.FallbackEventHandler; +import android.view.HapticFeedbackConstants; import android.view.KeyEvent; +import android.view.View; +import com.android.internal.policy.PhoneWindow; /** * @hide diff --git a/core/java/android/view/PhoneLayoutInflater.java b/core/java/com/android/internal/policy/PhoneLayoutInflater.java index 7d89a0b4bd2f..991b6bba7396 100644 --- a/core/java/android/view/PhoneLayoutInflater.java +++ b/core/java/com/android/internal/policy/PhoneLayoutInflater.java @@ -14,10 +14,12 @@ * limitations under the License. */ -package android.view; +package com.android.internal.policy; import android.content.Context; import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; /** * @hide diff --git a/core/java/android/view/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index a3e7a107495d..a578a6e5ddb2 100644 --- a/core/java/android/view/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.view; +package com.android.internal.policy; import static android.view.View.MeasureSpec.AT_MOST; import static android.view.View.MeasureSpec.EXACTLY; @@ -27,6 +27,34 @@ import android.app.ActivityManagerNative; import android.app.SearchManager; import android.os.UserHandle; +import android.view.ActionMode; +import android.view.ContextThemeWrapper; +import android.view.Display; +import android.view.Gravity; +import android.view.IRotationWatcher.Stub; +import android.view.IWindowManager; +import android.view.InputDevice; +import android.view.InputEvent; +import android.view.InputQueue; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.SearchEvent; +import android.view.SurfaceHolder.Callback2; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewManager; +import android.view.ViewParent; +import android.view.ViewRootImpl; +import android.view.ViewStub; +import android.view.ViewTreeObserver.OnPreDrawListener; +import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowManager; import com.android.internal.R; import com.android.internal.util.ScreenShapeHelper; import com.android.internal.view.FloatingActionMode; @@ -67,7 +95,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemProperties; import android.transition.Scene; import android.transition.Transition; import android.transition.TransitionInflater; @@ -140,7 +167,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private ViewGroup mContentRoot; - SurfaceHolder.Callback2 mTakeSurfaceCallback; + Callback2 mTakeSurfaceCallback; InputQueue.Callback mTakeInputQueueCallback; @@ -427,7 +454,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override - public void takeSurface(SurfaceHolder.Callback2 callback) { + public void takeSurface(Callback2 callback) { mTakeSurfaceCallback = callback; } @@ -2181,7 +2208,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private ActionBarContextView mPrimaryActionModeView; private PopupWindow mPrimaryActionModePopup; private Runnable mShowPrimaryActionModePopup; - private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener; + private OnPreDrawListener mFloatingToolbarPreDrawListener; private View mFloatingActionModeOriginatingView; private FloatingToolbar mFloatingToolbar; @@ -3354,7 +3381,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mContext, callback, originatingView, mFloatingToolbar); mFloatingActionModeOriginatingView = originatingView; mFloatingToolbarPreDrawListener = - new ViewTreeObserver.OnPreDrawListener() { + new OnPreDrawListener() { @Override public boolean onPreDraw() { mode.updateViewLocationInWindow(); @@ -4718,7 +4745,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } - static class RotationWatcher extends IRotationWatcher.Stub { + static class RotationWatcher extends Stub { private Handler mHandler; private final Runnable mRotationChanged = new Runnable() { public void run() { diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 60c5e420d24f..6f104dd0eb24 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -59,8 +59,7 @@ interface IInputMethodManager { int controlFlags, int softInputMode, int windowFlags, in EditorInfo attribute, IInputContext inputContext); - void showInputMethodPickerFromClient(in IInputMethodClient client, - int auxiliarySubtypeMode); + void showInputMethodPickerFromClient(in IInputMethodClient client); void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId); void setInputMethod(in IBinder token, String id); void setInputMethodAndSubtype(in IBinder token, String id, in InputMethodSubtype subtype); diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java index 929258d5937a..845d53a19213 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java @@ -162,8 +162,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView switchImeButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { mCallback.userActivity(); // Leave the screen on a bit longer - // Do not show auxiliary subtypes in password lock screen. - mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */); + mImm.showInputMethodPicker(); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 7077a17f00df..c62ad663da3d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -144,7 +144,7 @@ public class NavigationBarView extends LinearLayout { @Override public void onClick(View view) { ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE)) - .showInputMethodPicker(true /* showAuxiliarySubtypes */); + .showInputMethodPicker(); } }; diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 759a6bea345c..638965a18a43 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -2038,11 +2038,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (!mIWindowManager.inputMethodClientHasFocus(client)) { if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client); - setImeWindowVisibilityStatusHiddenLocked(); return false; } } catch (RemoteException e) { - setImeWindowVisibilityStatusHiddenLocked(); return false; } } @@ -2238,8 +2236,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @Override - public void showInputMethodPickerFromClient( - IInputMethodClient client, int auxiliarySubtypeMode) { + public void showInputMethodPickerFromClient(IInputMethodClient client) { if (!calledFromValidUser()) { return; } @@ -2252,8 +2249,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Always call subtype picker, because subtype picker is a superset of input method // picker. - mHandler.sendMessage(mCaller.obtainMessageI( - MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode)); + mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER); } } @@ -2599,25 +2595,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub SomeArgs args; switch (msg.what) { case MSG_SHOW_IM_SUBTYPE_PICKER: - final boolean showAuxSubtypes; - switch (msg.arg1) { - case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO: - // This is undocumented so far, but IMM#showInputMethodPicker() has been - // implemented so that auxiliary subtypes will be excluded when the soft - // keyboard is invisible. - showAuxSubtypes = mInputShown; - break; - case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES: - showAuxSubtypes = true; - break; - case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES: - showAuxSubtypes = false; - break; - default: - Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1); - return false; - } - showInputMethodMenu(showAuxSubtypes); + showInputMethodMenu(); return true; case MSG_SHOW_IM_SUBTYPE_ENABLER: @@ -2900,8 +2878,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure(); } - private void showInputMethodMenu(boolean showAuxSubtypes) { - if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes); + private void showInputMethodMenu() { + if (DEBUG) Slog.v(TAG, "Show switching menu"); final Context context = mContext; final boolean isScreenLocked = isScreenLocked(); @@ -2922,7 +2900,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final List<ImeSubtypeListItem> imList = mSwitchingController.getSortedInputMethodAndSubtypeListLocked( - true /* showSubtypes */, showAuxSubtypes, isScreenLocked); + true /* showSubtypes */, mInputShown, isScreenLocked); if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) { final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked(); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 51503ec295fc..dbd3676dff0e 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -93,7 +93,7 @@ import android.view.KeyCharacterMap; import android.view.KeyCharacterMap.FallbackAction; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.PhoneWindow; +import com.android.internal.policy.PhoneWindow; import android.view.Surface; import android.view.View; import android.view.ViewConfiguration; diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java index 9eea66338402..87762a63a058 100644 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java @@ -16,19 +16,15 @@ package android.view; -import com.android.ide.common.rendering.api.LayoutlibCallback; import com.android.ide.common.rendering.api.LayoutLog; +import com.android.ide.common.rendering.api.LayoutlibCallback; import com.android.ide.common.rendering.api.MergeCookie; import com.android.ide.common.rendering.api.ResourceReference; import com.android.ide.common.rendering.api.ResourceValue; import com.android.layoutlib.bridge.Bridge; -import com.android.layoutlib.bridge.BridgeConstants; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.support.RecyclerViewUtil; -import com.android.layoutlib.bridge.android.support.RecyclerViewUtil.LayoutManagerType; import com.android.layoutlib.bridge.impl.ParserFactory; -import com.android.layoutlib.bridge.impl.RenderSessionImpl; import com.android.resources.ResourceType; import com.android.util.Pair; @@ -233,22 +229,6 @@ public final class BridgeInflater extends LayoutInflater { if (viewKey != null) { bc.addViewKey(view, viewKey); } - if (RenderSessionImpl.isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) { - String type = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES, - BridgeConstants.ATTR_LAYOUT_MANAGER_TYPE); - if (type != null) { - LayoutManagerType layoutManagerType = LayoutManagerType.getByLogicalName(type); - if (layoutManagerType == null) { - layoutManagerType = LayoutManagerType.getByClassName(type); - } - if (layoutManagerType == null) { - // add the classname itself. - bc.addCookie(view, type); - } else { - bc.addCookie(view, layoutManagerType); - } - } - } } } diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java index ec3a8d627fcc..30512aad4509 100644 --- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java +++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java @@ -19,6 +19,7 @@ package android.view; import com.android.layoutlib.bridge.impl.ResourceHelper; import android.graphics.Canvas; +import android.graphics.Canvas_Delegate; import android.graphics.LinearGradient; import android.graphics.Outline; import android.graphics.Paint; @@ -125,6 +126,9 @@ public class RectShadowPainter { private static void sideShadow(Canvas canvas, Paint edgePaint, RectF edgeShadowRect, float dx, float dy, int rotations) { + if (isRectEmpty(edgeShadowRect)) { + return; + } int saved = canvas.save(); canvas.translate(dx, dy); canvas.rotate(rotations * PERPENDICULAR_ANGLE); @@ -153,4 +157,15 @@ public class RectShadowPainter { canvas.drawPath(path, paint); canvas.restoreToCount(saved); } + + /** + * Differs from {@link RectF#isEmpty()} as this first converts the rect to int and then checks. + * <p/> + * This is required because {@link Canvas_Delegate#native_drawRect(long, float, float, float, + * float, long)} casts the co-ordinates to int and we want to ensure that it doesn't end up + * drawing empty rectangles, which results in IllegalArgumentException. + */ + private static boolean isRectEmpty(RectF rect) { + return (int) rect.left >= (int) rect.right || (int) rect.top >= (int) rect.bottom; + } } 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 094778d2b4a5..eb5f59733ebf 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 @@ -93,6 +93,8 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE; + /** * Custom implementation of Context/Activity to handle non compiled resources. */ @@ -306,7 +308,7 @@ public final class BridgeContext extends Context { // check if this is a style resource if (value instanceof StyleResourceValue) { // get the id that will represent this style. - outValue.resourceId = getDynamicIdByStyle((StyleResourceValue)value); + outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value); return true; } @@ -812,6 +814,14 @@ public final class BridgeContext extends Context { } + @Override + public String getPackageName() { + if (mApplicationInfo.packageName == null) { + mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE); + } + return mApplicationInfo.packageName; + } + // ------------- private new methods /** @@ -1225,12 +1235,6 @@ public final class BridgeContext extends Context { } @Override - public String getPackageName() { - // pass - return null; - } - - @Override public String getBasePackageName() { // pass return null; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java index 2f45473bf53b..b98f96f27c91 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java @@ -16,6 +16,7 @@ package com.android.layoutlib.bridge.android; +import com.android.ide.common.rendering.api.RenderParams; import com.android.ide.common.rendering.api.SessionParams.Key; /** @@ -31,10 +32,21 @@ public final class RenderParamsFlags { new Key<String>("rootTag", String.class); public static final Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING = new Key<Boolean>("disableBitmapCaching", Boolean.class); - public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT = - new Key<Boolean>("recyclerViewSupport", Boolean.class); public static final Key<Boolean> FLAG_KEY_RENDER_ALL_DRAWABLE_STATES = new Key<Boolean>("renderAllDrawableStates", Boolean.class); + /** + * To tell LayoutLib that the IDE supports RecyclerView. + * <p/> + * Default is false. + */ + public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT = + new Key<Boolean>("recyclerViewSupport", Boolean.class); + /** + * The application package name. Used via + * {@link com.android.ide.common.rendering.api.LayoutlibCallback#getFlag(Key)} + */ + public static final Key<String> FLAG_KEY_APPLICATION_PACKAGE = + new Key<String>("applicationPackage", String.class); // Disallow instances. private RenderParamsFlags() {} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java index 9273ac248a13..e4c728842275 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java @@ -27,11 +27,12 @@ import com.android.layoutlib.bridge.android.RenderParamsFlags; import android.content.Context; import android.view.View; -import android.widget.LinearLayout; import java.lang.reflect.Method; -import static com.android.layoutlib.bridge.util.ReflectionUtils.*; +import static com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException; +import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; +import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; /** * Utility class for working with android.support.v7.widget.RecyclerView @@ -39,17 +40,15 @@ import static com.android.layoutlib.bridge.util.ReflectionUtils.*; @SuppressWarnings("SpellCheckingInspection") // for "recycler". public class RecyclerViewUtil { - /** - * Used by {@link LayoutManagerType}. - * <p/> - * Not declared inside the enum, since it needs to be accessible in the constructor. - */ - private static final Object CONTEXT = new Object(); - - public static final String CN_RECYCLER_VIEW = "android.support.v7.widget.RecyclerView"; + private static final String RV_PKG_PREFIX = "android.support.v7.widget."; + public static final String CN_RECYCLER_VIEW = RV_PKG_PREFIX + "RecyclerView"; private static final String CN_LAYOUT_MANAGER = CN_RECYCLER_VIEW + "$LayoutManager"; private static final String CN_ADAPTER = CN_RECYCLER_VIEW + "$Adapter"; + // LinearLayoutManager related constants. + private static final String CN_LINEAR_LAYOUT_MANAGER = RV_PKG_PREFIX + "LinearLayoutManager"; + private static final Class<?>[] LLM_CONSTRUCTOR_SIGNATURE = new Class<?>[]{Context.class}; + /** * Tries to create an Adapter ({@code android.support.v7.widget.RecyclerView.Adapter} and a * LayoutManager {@code RecyclerView.LayoutManager} and assign these to the {@code RecyclerView} @@ -71,37 +70,33 @@ public class RecyclerViewUtil { private static void setLayoutManager(@NonNull View recyclerView, @NonNull BridgeContext context, @NonNull LayoutlibCallback callback) throws ReflectionException { - Object cookie = context.getCookie(recyclerView); - assert cookie == null || cookie instanceof LayoutManagerType || cookie instanceof String; - if (!(cookie instanceof LayoutManagerType)) { - if (cookie != null) { - // TODO: When layoutlib API is updated, try to load the class with a null - // constructor or a constructor taking one argument - the context. - Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED, - "LayoutManager (" + cookie + ") not found, falling back to " + - "LinearLayoutManager", null); - } - cookie = LayoutManagerType.getDefault(); + if (getLayoutManager(recyclerView) == null) { + // Only set the layout manager if not already set by the recycler view. + Object layoutManager = createLayoutManager(context, callback); + setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager"); } - Object layoutManager = createLayoutManager((LayoutManagerType) cookie, context, callback); - setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager"); } + /** Creates a LinearLayoutManager using the provided context. */ @Nullable - private static Object createLayoutManager(@Nullable LayoutManagerType type, - @NonNull Context context, @NonNull LayoutlibCallback callback) + private static Object createLayoutManager(@NonNull Context context, + @NonNull LayoutlibCallback callback) throws ReflectionException { - if (type == null) { - type = LayoutManagerType.getDefault(); - } try { - return callback.loadView(type.getClassName(), type.getSignature(), type.getArgs(context)); + return callback.loadView(CN_LINEAR_LAYOUT_MANAGER, LLM_CONSTRUCTOR_SIGNATURE, + new Object[]{ context}); } catch (Exception e) { throw new ReflectionException(e); } } @Nullable + private static Object getLayoutManager(View recyclerview) throws ReflectionException { + Method getLayoutManager = getMethod(recyclerview.getClass(), "getLayoutManager"); + return getLayoutManager != null ? invoke(getLayoutManager, recyclerview) : null; + } + + @Nullable private static Object createAdapter(@NonNull SessionParams params) throws ReflectionException { Boolean ideSupport = params.getFlag(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT); if (ideSupport != Boolean.TRUE) { @@ -145,74 +140,4 @@ public class RecyclerViewUtil { } throw new RuntimeException("invalid object/classname combination."); } - - /** Supported LayoutManagers. */ - public enum LayoutManagerType { - LINEAR_LAYOUT_MANGER("Linear", - "android.support.v7.widget.LinearLayoutManager", - new Class[]{Context.class}, new Object[]{CONTEXT}), - GRID_LAYOUT_MANAGER("Grid", - "android.support.v7.widget.GridLayoutManager", - new Class[]{Context.class, int.class}, new Object[]{CONTEXT, 2}), - STAGGERED_GRID_LAYOUT_MANAGER("StaggeredGrid", - "android.support.v7.widget.StaggeredGridLayoutManager", - new Class[]{int.class, int.class}, new Object[]{2, LinearLayout.VERTICAL}); - - private String mLogicalName; - private String mClassName; - private Class[] mSignature; - private Object[] mArgs; - - LayoutManagerType(String logicalName, String className, Class[] signature, Object[] args) { - mLogicalName = logicalName; - mClassName = className; - mSignature = signature; - mArgs = args; - } - - String getClassName() { - return mClassName; - } - - Class[] getSignature() { - return mSignature; - } - - @NonNull - Object[] getArgs(Context context) { - Object[] args = new Object[mArgs.length]; - System.arraycopy(mArgs, 0, args, 0, mArgs.length); - for (int i = 0; i < args.length; i++) { - if (args[i] == CONTEXT) { - args[i] = context; - } - } - return args; - } - - @NonNull - public static LayoutManagerType getDefault() { - return LINEAR_LAYOUT_MANGER; - } - - @Nullable - public static LayoutManagerType getByLogicalName(@NonNull String logicalName) { - for (LayoutManagerType type : values()) { - if (logicalName.equals(type.mLogicalName)) { - return type; - } - } - return null; - } - - @Nullable - public static LayoutManagerType getByClassName(@NonNull String className) { - for (LayoutManagerType type : values()) { - if (className.equals(type.mClassName)) { - return type; - } - } - return null; - } - } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java index 9f9b968a6598..dc89d0c6546a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java @@ -74,7 +74,7 @@ public class Config { } public static String getTime(int platformVersion) { - if (platformVersion == 0) { + if (isGreaterOrEqual(platformVersion, LOLLIPOP_MR1)) { return "5:10"; } if (platformVersion < GINGERBREAD) { @@ -117,7 +117,7 @@ public class Config { } public static String getWifiIconType(int platformVersion) { - return platformVersion == 0 ? "xml" : "png"; + return isGreaterOrEqual(platformVersion, LOLLIPOP) ? "xml" : "png"; } /** diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java index 9450b6c3d3e7..04aadff95389 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java @@ -21,6 +21,10 @@ import com.android.resources.Density; import org.xmlpull.v1.XmlPullParserException; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.util.AttributeSet; +import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -29,6 +33,21 @@ public class NavigationBar extends CustomBar { /** Navigation bar background color attribute name. */ private static final String ATTR_COLOR = "navigationBarColor"; + /** + * Constructor to be used when creating the {@link NavigationBar} as a regular control. + * This is currently used by the theme editor. + */ + public NavigationBar(Context context, AttributeSet attrs) + throws XmlPullParserException { + this((BridgeContext) context, + Density.getEnum(((BridgeContext) context).getMetrics().densityDpi), + LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically + ((BridgeContext) context).getConfiguration().getLayoutDirection() == + View.LAYOUT_DIRECTION_RTL, + (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0, + context.getApplicationInfo().targetSdkVersion); + } + public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl, boolean rtlEnabled, int simulatedPlatformVersion) throws XmlPullParserException { super(context, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml", diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java index e5f1f68459e6..a0ed0e86d27f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java @@ -25,7 +25,9 @@ import com.android.resources.Density; import org.xmlpull.v1.XmlPullParserException; +import android.content.Context; import android.graphics.drawable.Drawable; +import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.widget.ImageView; @@ -39,7 +41,20 @@ public class StatusBar extends CustomBar { private final int mSimulatedPlatformVersion; /** Status bar background color attribute name. */ - private static final String ATTR_COLOR = "colorPrimaryDark"; + private static final String ATTR_COLOR = "statusBarColor"; + + /** + * Constructor to be used when creating the {@link StatusBar} as a regular control. This + * is currently used by the theme editor. + */ + public StatusBar(Context context, AttributeSet attrs) throws XmlPullParserException { + this((BridgeContext) context, + Density.getEnum(((BridgeContext) context).getMetrics().densityDpi), + LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically + ((BridgeContext) context).getConfiguration().getLayoutDirection() == + View.LAYOUT_DIRECTION_RTL, + context.getApplicationInfo().targetSdkVersion); + } public StatusBar(BridgeContext context, Density density, int direction, boolean RtlEnabled, int simulatedPlatformVersion) throws XmlPullParserException { @@ -50,6 +65,7 @@ public class StatusBar extends CustomBar { // FIXME: use FILL_H? setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT); + int color = getThemeAttrColor(ATTR_COLOR, true); setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java index 3dee1e23dfe2..26f9000ad945 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java @@ -42,6 +42,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}. * 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 d957259130f9..f6e5ef18a383 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 @@ -1075,7 +1075,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { boolean windowFullscreen = getBooleanThemeValue(resources, - "windowFullscreen", false, !isThemeAppCompat(resources)); + "windowFullscreen", false, true); if (!windowFullscreen && !mWindowIsFloating) { // default value @@ -1210,15 +1210,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). boolean isThemeAppCompat = false; for (int i = 0; i < 50; i++) { + if (defaultTheme == null) { + break; + } // for loop ensures that we don't run into cyclic theme inheritance. if (defaultTheme.getName().startsWith("Theme.AppCompat")) { isThemeAppCompat = true; break; } defaultTheme = resources.getParent(defaultTheme); - if (defaultTheme == null) { - break; - } } mIsThemeAppCompat = isThemeAppCompat; } diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class Binary files differindex d2524625e16c..8af93ebda1e4 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class Binary files differindex d109302c913f..069f9f7e826b 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class Binary files differindex 816ecc88cb54..36e2688c106f 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class Binary files differindex b034b75d0df2..ca438add633e 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class Binary files differindex f86b1d3d9e63..a98abf57306a 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class Binary files differindex 8bbae9035f0e..7d8cc8464334 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class Binary files differindex 8af745dc8d3b..7e6113b3aa11 100644 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png Binary files differnew file mode 100644 index 000000000000..c9b76bed16bf --- /dev/null +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml new file mode 100644 index 000000000000..2da2cb983a6c --- /dev/null +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml @@ -0,0 +1,393 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:ignore="HardcodedText,LabelFor,TextFields,ContentDescription,RtlHardcoded"> + + <FrameLayout + android:id="@id/frameLayout" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_alignParentTop="true" + android:layout_marginEnd="311dp"> + + <TextView + android:id="@id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left|top" + android:text="New Text" /> + </FrameLayout> + + <TextView + android:id="@id/textView2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentStart="true" + android:layout_below="@id/frameLayout" + android:text="Large Text" + android:textAppearance="?android:attr/textAppearanceLarge" /> + + <TextView + android:id="@id/textView3" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_toEndOf="@id/textView2" + android:text="Medium Text" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <TextView + android:id="@id/textView4" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignTop="@id/textView2" + android:layout_toEndOf="@id/textView2" + android:text="Small Text" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <Button + android:id="@id/button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/textView3" + android:layout_toEndOf="@id/textView4" + android:text="New Button" /> + + <Button + android:id="@id/button2" + style="?android:attr/buttonStyleSmall" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_toEndOf="@id/button" + android:text="New Button" /> + + <CheckBox + android:id="@id/checkBox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignEnd="@id/button" + android:layout_below="@id/button" + android:text="New CheckBox" /> + + <Switch + android:id="@id/switch1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentStart="true" + android:layout_below="@id/textView2" + android:text="New Switch" /> + + <ImageButton + android:id="@id/imageButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/button" + android:layout_toEndOf="@id/switch1" /> + + <ImageView + android:id="@id/imageView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/ic_launcher" + android:layout_below="@id/button" + android:layout_toEndOf="@id/imageButton" /> + + <GridLayout + android:id="@id/gridLayout" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentStart="true" + android:layout_below="@id/imageButton" + android:columnCount="2" + android:rowCount="2"> + + <ProgressBar + android:id="@id/progressBar" + style="?android:attr/progressBarStyleLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_column="0" + android:layout_row="0" /> + + <ProgressBar + android:id="@id/progressBar2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_column="1" + android:layout_row="0" /> + + <ProgressBar + android:id="@id/progressBar3" + style="?android:attr/progressBarStyleSmall" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_column="0" + android:layout_row="1" /> + + <ProgressBar + android:id="@id/progressBar4" + style="?android:attr/progressBarStyleHorizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_column="1" + android:layout_row="1" /> + </GridLayout> + + <SeekBar + android:id="@id/seekBar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignTop="@id/gridLayout" + android:layout_toEndOf="@id/gridLayout" /> + + <RatingBar + android:id="@id/ratingBar" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/switch2" + android:layout_toEndOf="@id/gridLayout" /> + + <Switch + android:id="@id/switch2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/seekBar" + android:layout_toEndOf="@id/switch1" + android:checked="true" /> + + <EditText + android:id="@id/editText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignBottom="@id/ratingBar" + android:layout_alignParentStart="true" + android:text="plain text" /> + + <EditText + android:id="@id/editText2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentStart="true" + android:layout_below="@id/ratingBar" + android:ems="3" + android:inputType="textPersonName" + android:text="Name" /> + + <EditText + android:id="@id/editText3" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_toEndOf="@id/editText2" + android:ems="2" + android:inputType="textPassword" + android:text="password" /> + + <EditText + android:id="@id/editText4" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignTop="@id/editText3" + android:layout_toEndOf="@id/editText3" + android:ems="3" + android:inputType="numberPassword" + android:text="numeric password" /> + + <EditText + android:id="@id/editText5" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/editText3" + android:layout_toStartOf="@id/editText6" + android:ems="7" + android:inputType="textEmailAddress" + android:text="email@domain.com" /> + + <EditText + android:id="@id/editText6" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_below="@id/editText4" + android:ems="7" + android:inputType="phone" + android:text="+11235554344" /> + + <EditText + android:id="@id/editText7" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/editText" + android:layout_toEndOf="@id/editText4" + android:ems="10" + android:inputType="textPostalAddress" + android:text="1600 Amphitheatre" /> + + <EditText + android:id="@id/editText9" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/editText5" + android:layout_alignParentStart="true" + android:ems="3" + android:inputType="time" + android:text="12:12" /> + + <RadioGroup + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/editText5" + android:layout_toEndOf="@id/editText9" + android:orientation="horizontal"> + + <RadioButton + android:id="@id/radioButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="New RadioButton" /> + + <RadioButton + android:id="@id/radioButton2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="New RadioButton" /> + + </RadioGroup> + + <CheckedTextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="CheckedTextView" + android:id="@id/checkedTextView" + android:layout_below="@id/button2" + android:layout_alignParentEnd="true" + android:layout_alignStart="@id/button2" /> + + <DialerFilter + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/checkBox" + android:layout_toStartOf="@id/quickContactBadge" + android:id="@id/dialerFilter" + android:layout_above="@id/ratingBar" + android:layout_toEndOf="@id/seekBar"> + + <EditText + android:id="@android:id/hint" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Hint" /> + + <EditText + android:id="@android:id/primary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@android:id/hint" + android:text="Primary" /> + </DialerFilter> + + <QuickContactBadge + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@id/quickContactBadge" + android:layout_below="@id/checkedTextView" + android:layout_alignParentEnd="true" /> + + <android.inputmethodservice.ExtractEditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="ExtractEditText" + android:id="@id/extractEditText" + android:layout_below="@id/editText9" + android:layout_alignParentEnd="true" + android:layout_alignStart="@id/checkedTextView" /> + + <ZoomControls + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@id/zoomControls" + android:layout_below="@id/editText9" + android:layout_alignParentStart="true" /> + + <TextureView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@id/textureView" + android:layout_below="@id/zoomControls" + android:layout_alignParentStart="true" + android:layout_alignBottom="@id/extractEditText" + android:layout_toStartOf="@id/editText3" /> + + <ListView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@id/listView" + android:layout_below="@id/textureView" + android:layout_alignParentStart="true" + android:layout_alignEnd="@id/textureView" /> + + <GridView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@id/gridView" + android:layout_below="@id/extractEditText" + android:layout_alignParentEnd="true" + android:layout_alignStart="@id/extractEditText" /> + + <ScrollView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@id/scrollView" + android:layout_below="@id/zoomControls" + android:layout_toRightOf="@id/listView" + android:layout_toLeftOf="@id/extractEditText"> + + <TabHost + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@id/tabHost"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <TabWidget + android:id="@android:id/tabs" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + <FrameLayout + android:id="@android:id/tabcontent" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:id="@id/linearLayout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"/> + + <LinearLayout + android:id="@id/linearLayout2" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"/> + + </FrameLayout> + </LinearLayout> + </TabHost> +</ScrollView> + + <SearchView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@id/searchView" + android:layout_alignBottom="@id/zoomControls" + android:layout_toEndOf="@id/seekBar" /> + +</RelativeLayout> diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/ids.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/ids.xml new file mode 100644 index 000000000000..1dc2fa02debd --- /dev/null +++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/ids.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <item type="id" name="button" /> + <item type="id" name="button2" /> + <item type="id" name="checkBox" /> + <item type="id" name="checkedTextView" /> + <item type="id" name="dialerFilter" /> + <item type="id" name="editText" /> + <item type="id" name="editText2" /> + <item type="id" name="editText3" /> + <item type="id" name="editText4" /> + <item type="id" name="editText5" /> + <item type="id" name="editText6" /> + <item type="id" name="editText7" /> + <item type="id" name="editText8" /> + <item type="id" name="editText9" /> + <item type="id" name="extractEditText" /> + <item type="id" name="frameLayout" /> + <item type="id" name="gridLayout" /> + <item type="id" name="gridView" /> + <item type="id" name="imageButton" /> + <item type="id" name="imageView" /> + <item type="id" name="linearLayout" /> + <item type="id" name="linearLayout2" /> + <item type="id" name="listView" /> + <item type="id" name="progressBar" /> + <item type="id" name="progressBar2" /> + <item type="id" name="progressBar3" /> + <item type="id" name="progressBar4" /> + <item type="id" name="quickContactBadge" /> + <item type="id" name="radioButton" /> + <item type="id" name="radioButton2" /> + <item type="id" name="ratingBar" /> + <item type="id" name="scrollView" /> + <item type="id" name="searchView" /> + <item type="id" name="seekBar" /> + <item type="id" name="spinner" /> + <item type="id" name="switch1" /> + <item type="id" name="switch2" /> + <item type="id" name="tabHost" /> + <item type="id" name="textView" /> + <item type="id" name="textView2" /> + <item type="id" name="textView3" /> + <item type="id" name="textView4" /> + <item type="id" name="textureView" /> + <item type="id" name="zoomControls" /> +</resources>
\ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java index ac23564012b3..f2a039ebcd6e 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java @@ -261,7 +261,7 @@ public class Main { new ResourceRepository(new FolderWrapper(TEST_RES_DIR + APP_TEST_RES), false) { @NonNull @Override - protected ResourceItem createResourceItem(String name) { + protected ResourceItem createResourceItem(@NonNull String name) { return new ResourceItem(name); } }; @@ -275,14 +275,27 @@ public class Main { ConfigGenerator.getEnumMap(attrs), getLayoutLog()); } + /** Text activity.xml */ + @Test + public void testActivity() throws ClassNotFoundException { + renderAndVerify("activity.xml", "activity.png"); + + } + + /** Test allwidgets.xml */ + @Test + public void testAllWidgets() throws ClassNotFoundException { + renderAndVerify("allwidgets.xml", "allwidgets.png"); + } + /** - * Create a new rendering session and test that rendering /layout/activity.xml on nexus 5 - * doesn't throw any exceptions. + * Create a new rendering session and test that rendering given layout on nexus 5 + * doesn't throw any exceptions and matches the provided image. */ - @Test - public void testRendering() throws ClassNotFoundException { + private void renderAndVerify(String layoutFileName, String goldenFileName) + throws ClassNotFoundException { // Create the layout pull parser. - LayoutPullParser parser = new LayoutPullParser(APP_TEST_RES + "/layout/activity.xml"); + LayoutPullParser parser = new LayoutPullParser(APP_TEST_RES + "/layout/" + layoutFileName); // Create LayoutLibCallback. LayoutLibTestCallback layoutLibCallback = new LayoutLibTestCallback(getLogger()); layoutLibCallback.initResources(); @@ -301,7 +314,7 @@ public class Main { session.getResult().getErrorMessage()); } try { - String goldenImagePath = APP_TEST_DIR + "/golden/activity.png"; + String goldenImagePath = APP_TEST_DIR + "/golden/" + goldenFileName; ImageUtils.requireSimilar(goldenImagePath, session.getImage()); } catch (IOException e) { getLogger().error(e, e.getMessage()); @@ -309,7 +322,7 @@ public class Main { } /** - * Uses Theme.Material and Target sdk version as 21. + * Uses Theme.Material and Target sdk version as 22. */ private SessionParams getSessionParams(LayoutPullParser layoutParser, ConfigGenerator configGenerator, LayoutLibTestCallback layoutLibCallback) { @@ -327,7 +340,7 @@ public class Main { resourceResolver, layoutLibCallback, 0, - 21, // TODO: Make it more configurable to run tests for various versions. + 22, // TODO: Make it more configurable to run tests for various versions. getLayoutLog()); } @@ -381,17 +394,17 @@ public class Main { } @Override - public void warning(String msgFormat, Object... args) { + public void warning(@NonNull String msgFormat, Object... args) { failWithMsg(msgFormat, args); } @Override - public void info(String msgFormat, Object... args) { + public void info(@NonNull String msgFormat, Object... args) { // pass. } @Override - public void verbose(String msgFormat, Object... args) { + public void verbose(@NonNull String msgFormat, Object... args) { // pass. } }; @@ -399,7 +412,7 @@ public class Main { return mLogger; } - private static void failWithMsg(String msgFormat, Object... args) { - fail(msgFormat == null || args == null ? "" : String.format(msgFormat, args)); + private static void failWithMsg(@NonNull String msgFormat, Object... args) { + fail(args == null ? "" : String.format(msgFormat, args)); } } diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java index a5c320294504..1191df635a2c 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java @@ -21,12 +21,11 @@ import com.android.ide.common.resources.configuration.CountryCodeQualifier; import com.android.ide.common.resources.configuration.DensityQualifier; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.common.resources.configuration.KeyboardStateQualifier; -import com.android.ide.common.resources.configuration.LanguageQualifier; import com.android.ide.common.resources.configuration.LayoutDirectionQualifier; +import com.android.ide.common.resources.configuration.LocaleQualifier; import com.android.ide.common.resources.configuration.NavigationMethodQualifier; import com.android.ide.common.resources.configuration.NetworkCodeQualifier; import com.android.ide.common.resources.configuration.NightModeQualifier; -import com.android.ide.common.resources.configuration.RegionQualifier; import com.android.ide.common.resources.configuration.ScreenDimensionQualifier; import com.android.ide.common.resources.configuration.ScreenOrientationQualifier; import com.android.ide.common.resources.configuration.ScreenRatioQualifier; @@ -158,10 +157,9 @@ public class ConfigGenerator { config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL)); config.setNightModeQualifier(new NightModeQualifier(NightMode.NOTNIGHT)); config.setCountryCodeQualifier(new CountryCodeQualifier()); - config.setLanguageQualifier(new LanguageQualifier()); config.setLayoutDirectionQualifier(new LayoutDirectionQualifier()); config.setNetworkCodeQualifier(new NetworkCodeQualifier()); - config.setRegionQualifier(new RegionQualifier()); + config.setLocaleQualifier(new LocaleQualifier()); config.setVersionQualifier(new VersionQualifier()); return config; } diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java index 0a5e7984a336..5b648efb1089 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java @@ -23,8 +23,8 @@ import com.android.ide.common.rendering.api.ILayoutPullParser; import com.android.ide.common.rendering.api.LayoutlibCallback; import com.android.ide.common.rendering.api.ResourceReference; import com.android.ide.common.rendering.api.ResourceValue; -import com.android.resources.ResourceType; import com.android.ide.common.resources.IntArrayWrapper; +import com.android.resources.ResourceType; import com.android.util.Pair; import com.android.utils.ILogger; @@ -36,6 +36,8 @@ import java.util.Map; import com.google.android.collect.Maps; +import static org.junit.Assert.fail; + @SuppressWarnings("deprecation") // For Pair public class LayoutLibTestCallback extends LayoutlibCallback { @@ -121,7 +123,7 @@ public class LayoutLibTestCallback extends LayoutlibCallback { @Override public ILayoutPullParser getParser(String layoutName) { - org.junit.Assert.fail("This method shouldn't be called by this version of LayoutLib."); + fail("This method shouldn't be called by this version of LayoutLib."); return null; } |