Fix for 2209086: Initial pass at new SlidingTab widget and integration into LockScreen.
Tested:
- unlock and mute/unmute
Not working:
- highlighting on right tab.
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
new file mode 100644
index 0000000..6bcecc3
--- /dev/null
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2009 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.internal.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Vibrator;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.ImageView.ScaleType;
+import com.android.internal.R;
+
+/**
+ * A special widget containing two Sliders and a threshold for each. Moving either slider beyond
+ * the threshold will cause the registered OnTriggerListener.onTrigger() to be called with
+ * {@link OnTriggerListener#LEFT_HANDLE} or {@link OnTriggerListener#RIGHT_HANDLE} to be called.
+ *
+ */
+public class SlidingTab extends ViewGroup {
+ private static final String LOG_TAG = "SlidingTab";
+ private static final boolean DBG = false;
+ private static final int HORIZONTAL = 0; // as defined in attrs.xml
+ private static final int VERTICAL = 1;
+ private static final int MSG_ANIMATE = 100;
+
+ // TODO: Make these configurable
+ private static final float TARGET_ZONE = 2.0f / 3.0f;
+ private static final long VIBRATE_SHORT = 30;
+ private static final long VIBRATE_LONG = 40;
+
+ private OnTriggerListener mOnTriggerListener;
+ private int mGrabbedState = OnTriggerListener.NO_HANDLE;
+ private boolean mTriggered = false;
+ private Vibrator mVibrator;
+ private float mDensity; // used to scale dimensions for bitmaps.
+
+ private final SlidingTabHandler mHandler = new SlidingTabHandler();
+
+ /**
+ * Either {@link #HORIZONTAL} or {@link #VERTICAL}.
+ */
+ private int mOrientation;
+
+ private Slider mLeftSlider;
+ private Slider mRightSlider;
+ private Slider mCurrentSlider;
+ private boolean mTracking;
+ private float mTargetZone;
+ private Slider mOtherSlider;
+ private boolean mAnimating;
+
+ /**
+ * Interface definition for a callback to be invoked when a tab is triggered
+ * by moving it beyond a target zone.
+ */
+ public interface OnTriggerListener {
+ /**
+ * The interface was triggered because the user let go of the handle without reaching the
+ * target zone.
+ */
+ public static final int NO_HANDLE = 0;
+
+ /**
+ * The interface was triggered because the user grabbed the left handle and moved it past
+ * the target zone.
+ */
+ public static final int LEFT_HANDLE = 1;
+
+ /**
+ * The interface was triggered because the user grabbed the right handle and moved it past
+ * the target zone.
+ */
+ public static final int RIGHT_HANDLE = 2;
+
+ /**
+ * Called when the user moves a handle beyond the target zone.
+ *
+ * @param v The view that was triggered.
+ * @param whichHandle Which "dial handle" the user grabbed,
+ * either {@link #LEFT_HANDLE}, {@link #RIGHT_HANDLE}.
+ */
+ void onTrigger(View v, int whichHandle);
+
+ /**
+ * Called when the "grabbed state" changes (i.e. when the user either grabs or releases
+ * one of the handles.)
+ *
+ * @param v the view that was triggered
+ * @param grabbedState the new state: {@link #NO_HANDLE}, {@link #LEFT_HANDLE},
+ * or {@link #RIGHT_HANDLE}.
+ */
+ void onGrabbedStateChange(View v, int grabbedState);
+ }
+
+ /**
+ * Simple container class for all things pertinent to a slider.
+ * A slider consists of 3 Views:
+ *
+ * {@link #tab} is the tab shown on the screen in the default state.
+ * {@link #text} is the view revealed as the user slides the tab out.
+ * {@link #target} is the target the user must drag the slider past to trigger the slider.
+ *
+ */
+ private static class Slider {
+ /**
+ * Tab alignment - determines which side the tab should be drawn on
+ */
+ public static final int ALIGN_LEFT = 0;
+ public static final int ALIGN_RIGHT = 1;
+ public static final int ALIGN_TOP = 2;
+ public static final int ALIGN_BOTTOM = 3;
+
+ /**
+ * States for the view.
+ */
+ private static final int STATE_NORMAL = 0;
+ private static final int STATE_PRESSED = 1;
+ private static final int STATE_ACTIVE = 2;
+
+ private final ImageView tab;
+ private final TextView text;
+ private final ImageView target;
+
+ /**
+ * Constructor
+ *
+ * @param parent the container view of this one
+ * @param tabId drawable for the tab
+ * @param barId drawable for the bar
+ * @param targetId drawable for the target
+ */
+ Slider(ViewGroup parent, int tabId, int barId, int targetId) {
+ // Create tab
+ tab = new ImageView(parent.getContext());
+ tab.setBackgroundResource(tabId);
+ tab.setScaleType(ScaleType.CENTER);
+ tab.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+
+ // Create hint TextView
+ text = new TextView(parent.getContext());
+ text.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.FILL_PARENT));
+ text.setBackgroundResource(barId);
+ text.setTextAppearance(parent.getContext(), R.style.TextAppearance_SlidingTabNormal);
+ // hint.setSingleLine(); // Hmm.. this causes the text to disappear off-screen
+
+ // Create target
+ target = new ImageView(parent.getContext());
+ target.setImageResource(targetId);
+ target.setScaleType(ScaleType.CENTER);
+ target.setLayoutParams(
+ new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ target.setVisibility(View.INVISIBLE);
+
+ parent.addView(target); // this needs to be first - relies on painter's algorithm
+ parent.addView(tab);
+ parent.addView(text);
+ }
+
+ void setIcon(int iconId) {
+ tab.setImageResource(iconId);
+ }
+
+ void setTabBackgroundResource(int tabId) {
+ tab.setBackgroundResource(tabId);
+ }
+
+ void setBarBackgroundResource(int barId) {
+ text.setBackgroundResource(barId);
+ }
+
+ void setHintText(int resId) {
+ // TODO: Text should be blank if widget is vertical
+ text.setText(resId);
+ }
+
+ void hide() {
+ // TODO: Animate off the screen
+ text.setVisibility(View.INVISIBLE);
+ tab.setVisibility(View.INVISIBLE);
+ target.setVisibility(View.INVISIBLE);
+ }
+
+ void setState(int state) {
+ text.setPressed(state == STATE_PRESSED);
+ tab.setPressed(state == STATE_PRESSED);
+ if (state == STATE_ACTIVE) {
+ final int[] activeState = new int[] {com.android.internal.R.attr.state_active};
+ if (text.getBackground().isStateful()) {
+ text.getBackground().setState(activeState);
+ }
+ if (tab.getBackground().isStateful()) {
+ tab.getBackground().setState(activeState);
+ }
+ text.setTextAppearance(text.getContext(), R.style.TextAppearance_SlidingTabActive);
+ } else {
+ text.setTextAppearance(text.getContext(), R.style.TextAppearance_SlidingTabNormal);
+ }
+ }
+
+ void showTarget() {
+ target.setVisibility(View.VISIBLE);
+ }
+
+ void reset() {
+ setState(STATE_NORMAL);
+ text.setVisibility(View.VISIBLE);
+ text.setTextAppearance(text.getContext(), R.style.TextAppearance_SlidingTabNormal);
+ tab.setVisibility(View.VISIBLE);
+ target.setVisibility(View.INVISIBLE);
+ }
+
+ void setTarget(int targetId) {
+ target.setImageResource(targetId);
+ }
+
+ /**
+ * Layout the given widgets within the parent.
+ *
+ * @param l the parent's left border
+ * @param t the parent's top border
+ * @param r the parent's right border
+ * @param b the parent's bottom border
+ * @param alignment which side to align the widget to
+ */
+ void layout(int l, int t, int r, int b, int alignment) {
+ final int handleWidth = tab.getBackground().getIntrinsicWidth();
+ final int handleHeight = tab.getBackground().getIntrinsicHeight();
+ final int targetWidth = target.getDrawable().getIntrinsicWidth();
+ final int targetHeight = target.getDrawable().getIntrinsicHeight();
+ final int parentWidth = r - l;
+ final int parentHeight = b - t;
+
+ final int leftTarget = (int) (TARGET_ZONE * parentWidth) - targetWidth + handleWidth / 2;
+ final int rightTarget = (int) ((1.0f - TARGET_ZONE) * parentWidth) - handleWidth / 2;
+ final int left = (parentWidth - handleWidth) / 2;
+ final int right = left + handleWidth;
+
+ if (alignment == ALIGN_LEFT || alignment == ALIGN_RIGHT) {
+ // horizontal
+ final int targetTop = (parentHeight - targetHeight) / 2;
+ final int targetBottom = targetTop + targetHeight;
+ final int top = (parentHeight - handleHeight) / 2;
+ final int bottom = (parentHeight + handleHeight) / 2;
+ if (alignment == ALIGN_LEFT) {
+ tab.layout(0, top, handleWidth, bottom);
+ text.layout(0 - parentWidth, top, 0, bottom);
+ text.setGravity(Gravity.RIGHT);
+ target.layout(leftTarget, targetTop, leftTarget + targetWidth, targetBottom);
+ } else {
+ tab.layout(parentWidth - handleWidth, top, parentWidth, bottom);
+ text.layout(parentWidth, top, parentWidth + parentWidth, bottom);
+ target.layout(rightTarget, targetTop, rightTarget + targetWidth, targetBottom);
+ text.setGravity(Gravity.TOP);
+ }
+ } else {
+ // vertical
+ final int targetLeft = (parentWidth - targetWidth) / 2;
+ final int targetRight = (parentWidth + targetWidth) / 2;
+ final int top = (int) (TARGET_ZONE * parentHeight) + handleHeight / 2 - targetHeight;
+ final int bottom = (int) ((1.0f - TARGET_ZONE) * parentHeight) - handleHeight / 2;
+ if (alignment == ALIGN_TOP) {
+ tab.layout(left, 0, right, handleHeight);
+ text.layout(left, 0 - parentHeight, right, 0);
+ target.layout(targetLeft, top, targetRight, top + targetHeight);
+ } else {
+ tab.layout(left, parentHeight - handleHeight, right, parentHeight);
+ text.layout(left, parentHeight, right, parentHeight + parentHeight);
+ target.layout(targetLeft, bottom, targetRight, bottom + targetHeight);
+ }
+ }
+ }
+
+ public int getTabWidth() {
+ return tab.getDrawable().getIntrinsicWidth();
+ }
+
+ public int getTabHeight() {
+ return tab.getDrawable().getIntrinsicHeight();
+ }
+ }
+
+ public SlidingTab(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Constructor used when this widget is created from a layout file.
+ */
+ public SlidingTab(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingTab);
+ mOrientation = a.getInt(R.styleable.SlidingTab_orientation, HORIZONTAL);
+ a.recycle();
+
+ Resources r = getResources();
+ mDensity = r.getDisplayMetrics().density;
+ if (DBG) log("- Density: " + mDensity);
+
+ mLeftSlider = new Slider(this,
+ R.drawable.jog_tab_left_generic,
+ R.drawable.jog_tab_bar_left_generic,
+ R.drawable.jog_tab_target_gray);
+ mRightSlider = new Slider(this,
+ R.drawable.jog_tab_right_generic,
+ R.drawable.jog_tab_bar_right_generic,
+ R.drawable.jog_tab_target_gray);
+
+ // setBackgroundColor(0x80808080);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+ int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+
+ int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+ int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) {
+ throw new RuntimeException(LOG_TAG + " cannot have UNSPECIFIED dimensions");
+ }
+
+ final int leftTabWidth = (int) (mDensity * mLeftSlider.getTabWidth() + 0.5f);
+ final int rightTabWidth = (int) (mDensity * mRightSlider.getTabWidth() + 0.5f);
+ final int leftTabHeight = (int) (mDensity * mLeftSlider.getTabHeight() + 0.5f);
+ final int rightTabHeight = (int) (mDensity * mRightSlider.getTabHeight() + 0.5f);
+ final int width;
+ final int height;
+ if (isHorizontal()) {
+ width = Math.max(widthSpecSize, leftTabWidth + rightTabWidth);
+ height = Math.max(leftTabHeight, rightTabHeight);
+ } else {
+ width = Math.max(leftTabWidth, rightTabHeight);
+ height = Math.max(heightSpecSize, leftTabHeight + rightTabHeight);
+ }
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ final int action = event.getAction();
+ final float x = event.getX();
+ final float y = event.getY();
+
+ final Rect frame = new Rect();
+
+ if (mAnimating) {
+ return false;
+ }
+
+ View leftHandle = mLeftSlider.tab;
+ leftHandle.getHitRect(frame);
+ boolean leftHit = frame.contains((int) x, (int) y);
+
+ View rightHandle = mRightSlider.tab;
+ rightHandle.getHitRect(frame);
+ boolean rightHit = frame.contains((int)x, (int) y);
+
+ if (!mTracking && !(leftHit || rightHit)) {
+ return false;
+ }
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN: {
+ mTracking = true;
+ mTriggered = false;
+ vibrate(VIBRATE_SHORT);
+ if (leftHit) {
+ mCurrentSlider = mLeftSlider;
+ mOtherSlider = mRightSlider;
+ mTargetZone = isHorizontal() ? TARGET_ZONE : 1.0f - TARGET_ZONE;
+ setGrabbedState(OnTriggerListener.LEFT_HANDLE);
+ } else {
+ mCurrentSlider = mRightSlider;
+ mOtherSlider = mLeftSlider;
+ mTargetZone = isHorizontal() ? 1.0f - TARGET_ZONE : TARGET_ZONE;
+ setGrabbedState(OnTriggerListener.RIGHT_HANDLE);
+ }
+ mCurrentSlider.setState(Slider.STATE_PRESSED);
+ mCurrentSlider.showTarget();
+ mOtherSlider.hide();
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mTracking) {
+ final int action = event.getAction();
+ final float x = event.getX();
+ final float y = event.getY();
+ final View handle = mCurrentSlider.tab;
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ moveHandle(x, y);
+ float position = isHorizontal() ? x : y;
+ float target = mTargetZone * (isHorizontal() ? getWidth() : getHeight());
+ boolean targetZoneReached;
+ if (isHorizontal()) {
+ targetZoneReached = mCurrentSlider == mLeftSlider ?
+ position > target : position < target;
+ } else {
+ targetZoneReached = mCurrentSlider == mLeftSlider ?
+ position < target : position > target;
+ }
+ if (!mTriggered && targetZoneReached) {
+ mTriggered = true;
+ mTracking = false;
+ mCurrentSlider.setState(Slider.STATE_ACTIVE);
+ dispatchTriggerEvent(mCurrentSlider == mLeftSlider ?
+ OnTriggerListener.LEFT_HANDLE : OnTriggerListener.RIGHT_HANDLE);
+
+ // TODO: This is a place holder for the real animation. It just holds
+ // the screen for 500ms.
+ mAnimating = true;
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ resetView();
+ mAnimating = false;
+ }
+ }, 500);
+ }
+
+ if (isHorizontal() && (y <= handle.getBottom() && y >= handle.getTop()) ||
+ !isHorizontal() && (x >= handle.getLeft() && x <= handle.getRight()) ) {
+ break;
+ }
+ // Intentionally fall through - we're outside tracking rectangle
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mTracking = false;
+ mTriggered = false;
+ resetView();
+ setGrabbedState(OnTriggerListener.NO_HANDLE);
+ break;
+ }
+ }
+
+ return mTracking || super.onTouchEvent(event);
+ }
+
+ private boolean isHorizontal() {
+ return mOrientation == HORIZONTAL;
+ }
+
+ private void resetView() {
+ mLeftSlider.reset();
+ mRightSlider.reset();
+ onLayout(true, getLeft(), getTop(), getLeft() + getWidth(), getTop() + getHeight());
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ if (!changed) return;
+
+ // Center the widgets in the view
+ mLeftSlider.layout(l, t, r, b, isHorizontal() ? Slider.ALIGN_LEFT : Slider.ALIGN_BOTTOM);
+ mRightSlider.layout(l, t, r, b, isHorizontal() ? Slider.ALIGN_RIGHT : Slider.ALIGN_TOP);
+
+ invalidate(); // TODO: be more conservative about what we're invalidating
+ }
+
+ private void moveHandle(float x, float y) {
+ final View handle = mCurrentSlider.tab;
+ final View content = mCurrentSlider.text;
+ if (isHorizontal()) {
+ int deltaX = (int) x - handle.getLeft() - (handle.getWidth() / 2);
+ handle.offsetLeftAndRight(deltaX);
+ content.offsetLeftAndRight(deltaX);
+ } else {
+ int deltaY = (int) y - handle.getTop() - (handle.getHeight() / 2);
+ handle.offsetTopAndBottom(deltaY);
+ content.offsetTopAndBottom(deltaY);
+ }
+ invalidate(); // TODO: be more conservative about what we're invalidating
+ }
+
+ /**
+ * Sets the left handle icon to a given resource.
+ *
+ * The resource should refer to a Drawable object, or use 0 to remove
+ * the icon.
+ *
+ * @param iconId the resource ID of the icon drawable
+ * @param targetId the resource of the target drawable
+ * @param barId the resource of the bar drawable (stateful)
+ * @param tabId the resource of the
+ */
+ public void setLeftTabResources(int iconId, int targetId, int barId, int tabId) {
+ mLeftSlider.setIcon(iconId);
+ mLeftSlider.setTarget(targetId);
+ mLeftSlider.setBarBackgroundResource(barId);
+ mLeftSlider.setTabBackgroundResource(tabId);
+ }
+
+ /**
+ * Sets the left handle hint text to a given resource string.
+ *
+ * @param resId
+ */
+ public void setLeftHintText(int resId) {
+ mLeftSlider.setHintText(resId);
+ }
+
+ /**
+ * Sets the right handle icon to a given resource.
+ *
+ * The resource should refer to a Drawable object, or use 0 to remove
+ * the icon.
+ *
+ * @param iconId the resource ID of the icon drawable
+ * @param targetId the resource of the target drawable
+ * @param barId the resource of the bar drawable (stateful)
+ * @param tabId the resource of the
+ */
+ public void setRightTabResources(int iconId, int targetId, int barId, int tabId) {
+ mRightSlider.setIcon(iconId);
+ mRightSlider.setTarget(targetId);
+ mRightSlider.setBarBackgroundResource(barId);
+ mRightSlider.setTabBackgroundResource(tabId);
+ }
+
+ /**
+ * Sets the left handle hint text to a given resource string.
+ *
+ * @param resId
+ */
+ public void setRightHintText(int resId) {
+ mRightSlider.setHintText(resId);
+ }
+
+ /**
+ * Triggers haptic feedback.
+ */
+ private synchronized void vibrate(long duration) {
+ if (mVibrator == null) {
+ mVibrator = (android.os.Vibrator)
+ getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ }
+ mVibrator.vibrate(duration);
+ }
+
+ /**
+ * Registers a callback to be invoked when the user triggers an event.
+ *
+ * @param listener the OnDialTriggerListener to attach to this view
+ */
+ public void setOnTriggerListener(OnTriggerListener listener) {
+ mOnTriggerListener = listener;
+ }
+
+ /**
+ * Dispatches a trigger event to listener. Ignored if a listener is not set.
+ * @param whichHandle the handle that triggered the event.
+ */
+ private void dispatchTriggerEvent(int whichHandle) {
+ vibrate(VIBRATE_LONG);
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onTrigger(this, whichHandle);
+ }
+ }
+
+ /**
+ * Sets the current grabbed state, and dispatches a grabbed state change
+ * event to our listener.
+ */
+ private void setGrabbedState(int newState) {
+ if (newState != mGrabbedState) {
+ mGrabbedState = newState;
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState);
+ }
+ }
+ }
+
+ private class SlidingTabHandler extends Handler {
+ public void handleMessage(Message m) {
+ switch (m.what) {
+ case MSG_ANIMATE:
+ doAnimation();
+ break;
+ }
+ }
+ }
+
+ private void doAnimation() {
+ if (mAnimating) {
+
+ }
+ }
+
+ private void log(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+}
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_confirm_gray.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_gray.9.png
new file mode 100644
index 0000000..92db44f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_confirm_green.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_green.9.png
new file mode 100644
index 0000000..0bed1a0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_confirm_red.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_red.9.png
new file mode 100644
index 0000000..81fbe5a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_confirm_yellow.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_yellow.9.png
new file mode 100644
index 0000000..d9c33fb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_normal.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_normal.9.png
new file mode 100644
index 0000000..1cf7f1c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_bar_pressed.9.png b/core/res/res/drawable-hdpi/jog_tab_bar_pressed.9.png
new file mode 100644
index 0000000..c7b367e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_bar_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
new file mode 100644
index 0000000..3499208
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
new file mode 100644
index 0000000..91eaec8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_red.png
new file mode 100644
index 0000000..8818b9e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
new file mode 100644
index 0000000..e5bc5f6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_normal.png b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
new file mode 100644
index 0000000..5326c7c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_pressed.png b/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
new file mode 100644
index 0000000..7b906df
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
new file mode 100644
index 0000000..ea8c315
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
new file mode 100644
index 0000000..aa0ceb9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_red.png
new file mode 100644
index 0000000..d772fb6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
new file mode 100644
index 0000000..3cfeb67
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_normal.png b/core/res/res/drawable-hdpi/jog_tab_right_normal.png
new file mode 100644
index 0000000..da7726b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_pressed.png b/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
new file mode 100644
index 0000000..450a325
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_gray.png b/core/res/res/drawable-hdpi/jog_tab_target_gray.png
new file mode 100644
index 0000000..e7ef129
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_green.png b/core/res/res/drawable-hdpi/jog_tab_target_green.png
new file mode 100644
index 0000000..17f6b10
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_red.png b/core/res/res/drawable-hdpi/jog_tab_target_red.png
new file mode 100644
index 0000000..8db20bb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_target_yellow.png b/core/res/res/drawable-hdpi/jog_tab_target_yellow.png
new file mode 100644
index 0000000..15045b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/btn_lock_normal.9.png b/core/res/res/drawable-land-hdpi/btn_lock_normal.9.png
new file mode 100644
index 0000000..f1dac62
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/btn_lock_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/ic_jog_dial_sound_off.png b/core/res/res/drawable-land-hdpi/ic_jog_dial_sound_off.png
new file mode 100755
index 0000000..d73db48
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/ic_jog_dial_sound_off.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/ic_jog_dial_sound_on.png b/core/res/res/drawable-land-hdpi/ic_jog_dial_sound_on.png
new file mode 100755
index 0000000..90da6e3
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/ic_jog_dial_sound_on.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/ic_jog_dial_unlock.png b/core/res/res/drawable-land-hdpi/ic_jog_dial_unlock.png
new file mode 100755
index 0000000..a9af1af
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/ic_jog_dial_unlock.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_gray.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_gray.9.png
new file mode 100644
index 0000000..c0f7706
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_gray.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_green.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_green.9.png
new file mode 100644
index 0000000..0f2ce13
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_green.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_red.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_red.9.png
new file mode 100644
index 0000000..a34eb7d
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_red.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_yellow.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_yellow.9.png
new file mode 100644
index 0000000..e143356
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_confirm_yellow.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_normal.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_normal.9.png
new file mode 100644
index 0000000..b5837f7
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_bar_pressed.9.png b/core/res/res/drawable-land-hdpi/jog_tab_bar_pressed.9.png
new file mode 100644
index 0000000..79ad83d
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_bar_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_gray.png
new file mode 100644
index 0000000..9c63b22
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_green.png
new file mode 100644
index 0000000..4f9877c
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_red.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_red.png
new file mode 100644
index 0000000..bdce97d
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_yellow.png
new file mode 100644
index 0000000..327fc2c
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_normal.png b/core/res/res/drawable-land-hdpi/jog_tab_left_normal.png
new file mode 100644
index 0000000..e69d91c
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_left_pressed.png b/core/res/res/drawable-land-hdpi/jog_tab_left_pressed.png
new file mode 100644
index 0000000..b6153d8
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_gray.png
new file mode 100644
index 0000000..6e3e00b
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_green.png
new file mode 100644
index 0000000..dae9efc
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_red.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_red.png
new file mode 100644
index 0000000..9de3158
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_yellow.png
new file mode 100644
index 0000000..8c9f180
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_normal.png b/core/res/res/drawable-land-hdpi/jog_tab_right_normal.png
new file mode 100644
index 0000000..0c4faf2
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_right_pressed.png b/core/res/res/drawable-land-hdpi/jog_tab_right_pressed.png
new file mode 100644
index 0000000..4ec7b56
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_gray.png b/core/res/res/drawable-land-hdpi/jog_tab_target_gray.png
new file mode 100644
index 0000000..4150007
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_gray.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_green.png b/core/res/res/drawable-land-hdpi/jog_tab_target_green.png
new file mode 100644
index 0000000..ef18b6c
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_green.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_red.png b/core/res/res/drawable-land-hdpi/jog_tab_target_red.png
new file mode 100644
index 0000000..5dfaa5f
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_red.png
Binary files differ
diff --git a/core/res/res/drawable-land-hdpi/jog_tab_target_yellow.png b/core/res/res/drawable-land-hdpi/jog_tab_target_yellow.png
new file mode 100644
index 0000000..d0509fa
--- /dev/null
+++ b/core/res/res/drawable-land-hdpi/jog_tab_target_yellow.png
Binary files differ
diff --git a/core/res/res/drawable/jog_tab_bar_left_generic.xml b/core/res/res/drawable/jog_tab_bar_left_generic.xml
new file mode 100644
index 0000000..de1a42f
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_bar_left_generic.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_bar_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_bar_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_bar_confirm_gray" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_bar_left_unlock.xml b/core/res/res/drawable/jog_tab_bar_left_unlock.xml
new file mode 100644
index 0000000..b1d7c31
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_bar_left_unlock.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_bar_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_bar_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_bar_confirm_green" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_bar_right_generic.xml b/core/res/res/drawable/jog_tab_bar_right_generic.xml
new file mode 100644
index 0000000..de1a42f
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_bar_right_generic.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_bar_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_bar_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_bar_confirm_gray" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_bar_right_sound_off.xml b/core/res/res/drawable/jog_tab_bar_right_sound_off.xml
new file mode 100644
index 0000000..de1a42f
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_bar_right_sound_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_bar_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_bar_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_bar_confirm_gray" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_bar_right_sound_on.xml b/core/res/res/drawable/jog_tab_bar_right_sound_on.xml
new file mode 100644
index 0000000..febe32a
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_bar_right_sound_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_bar_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_bar_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_bar_confirm_yellow" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_left_generic.xml b/core/res/res/drawable/jog_tab_left_generic.xml
new file mode 100644
index 0000000..ed6d98b
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_left_generic.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_left_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_left_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_left_confirm_gray" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_left_unlock.xml b/core/res/res/drawable/jog_tab_left_unlock.xml
new file mode 100644
index 0000000..18ec7fa
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_left_unlock.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_left_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_left_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_left_confirm_green" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_right_generic.xml b/core/res/res/drawable/jog_tab_right_generic.xml
new file mode 100644
index 0000000..e173f2a
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_right_generic.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_right_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_right_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_right_confirm_gray" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_right_sound_off.xml b/core/res/res/drawable/jog_tab_right_sound_off.xml
new file mode 100644
index 0000000..e173f2a
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_right_sound_off.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_right_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_right_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_right_confirm_gray" />
+
+</selector>
diff --git a/core/res/res/drawable/jog_tab_right_sound_on.xml b/core/res/res/drawable/jog_tab_right_sound_on.xml
new file mode 100644
index 0000000..61f677c
--- /dev/null
+++ b/core/res/res/drawable/jog_tab_right_sound_on.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- StateListDrawable used for buttons in the in-call onscreen touch UI. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/jog_tab_right_pressed" />
+
+ <item android:state_enabled="true"
+ android:drawable="@drawable/jog_tab_right_normal" />
+
+ <item android:state_active="true"
+ android:drawable="@drawable/jog_tab_right_confirm_yellow" />
+
+</selector>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
new file mode 100644
index 0000000..84b5751
--- /dev/null
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2009, 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 is the general lock screen which shows information about the
+ state of the device, as well as instructions on how to get past it
+ depending on the state of the device. It is the same for landscape
+ and portrait.-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tabunlock="http://schemas.android.com/apk/res/com.android.tabunlock"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/root">
+
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="#70000000"
+ android:gravity="center_horizontal">
+
+ <TextView
+ android:id="@+id/carrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="20dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ <TextView
+ android:id="@+id/time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/carrier"
+ android:layout_marginTop="25dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textSize="55sp"
+ />
+
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/time"
+ android:layout_marginTop="-12dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
+ <View
+ android:id="@+id/divider"
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:layout_marginTop="10dip"
+ android:layout_below="@id/date"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+
+ <TextView
+ android:id="@+id/status1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/divider"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ android:drawablePadding="4dip"
+ />
+
+ <TextView
+ android:id="@+id/status2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/status1"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ android:drawablePadding="4dip"
+ />
+
+ <TextView
+ android:id="@+id/screenLocked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/status2"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ android:gravity="center"
+ android:layout_marginTop="12dip"
+ />
+
+ <com.android.internal.widget.SlidingTab
+ android:id="@+id/tab_selector"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="50dip"
+ />
+
+ <!-- emergency call button shown when sim is missing or PUKd -->
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/screenLocked"
+ android:layout_marginTop="24dip"
+ android:drawableLeft="@drawable/ic_emergency"
+ android:drawablePadding="8dip"
+ />
+
+ </RelativeLayout>
+
+</FrameLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
new file mode 100644
index 0000000..6aed301
--- /dev/null
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2009, 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 is the general lock screen which shows information about the
+ state of the device, as well as instructions on how to get past it
+ depending on the state of the device.-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tabunlock="http://schemas.android.com/apk/res/com.android.tabunlock"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ android:background="#70000000"
+ android:id="@+id/root">
+
+ <!-- left side -->
+ <RelativeLayout
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1.0"
+ android:gravity="center_horizontal">
+
+ <TextView
+ android:id="@+id/carrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="20dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ <TextView
+ android:id="@+id/time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/carrier"
+ android:layout_marginTop="25dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textSize="55sp"
+ />
+
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/time"
+ android:layout_marginTop="-12dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
+ <View
+ android:id="@+id/divider"
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:layout_marginTop="10dip"
+ android:layout_below="@id/date"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+
+ <TextView
+ android:id="@+id/status1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/divider"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ android:drawablePadding="4dip"
+ />
+
+ <TextView
+ android:id="@+id/status2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/status1"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ android:drawablePadding="4dip"
+ />
+
+ <TextView
+ android:id="@+id/screenLocked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/status2"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ android:gravity="center"
+ android:layout_marginTop="12dip"
+ />
+
+ <!-- emergency call button shown when sim is missing or PUKd -->
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/screenLocked"
+ android:layout_marginTop="24dip"
+ android:drawableLeft="@drawable/ic_emergency"
+ android:drawablePadding="8dip"
+ />
+ </RelativeLayout>
+
+ <!-- right side -->
+ <com.android.internal.widget.SlidingTab
+ android:id="@+id/tab_selector"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_marginBottom="50dip"
+ />
+
+</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 81da739..50382b3 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3559,4 +3559,14 @@
<attr name="detailSocialSummary" format="boolean" />
</declare-styleable>
+ <!-- =============================== -->
+ <!-- TabSelector class attributes -->
+ <!-- =============================== -->
+ <eat-comment />
+
+ <declare-styleable name="SlidingTab">
+ <!-- Use "horizontal" for a row, "vertical" for a column. The default is horizontal. -->
+ <attr name="orientation" />
+ </declare-styleable>
+
</resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 5d3069b..3c0f0a4 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -84,6 +84,10 @@
<color name="search_url_text_selected">@android:color/black</color>
<color name="search_url_text_pressed">@android:color/black</color>
<color name="search_widget_corpus_item_background">@android:color/lighter_gray</color>
+
+ <!-- SlidingTab -->
+ <color name="sliding_tab_text_color_active">@android:color/black</color>
+ <color name="sliding_tab_text_color_shadow">@android:color/black</color>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index de30fe7..d1ae571 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1434,6 +1434,10 @@
<!-- Displayed in a progress dialog while a username and password are being checked. -->
<string name="lockscreen_glogin_checking_password">Checking...</string>
+ <!-- Displayed on lock screen's left tab - unlock -->
+ <string name="lockscreen_unlock_label">Unlock</string>
+ <!-- Displayed on lock screen's right tab - mute/unmute -->
+ <string name="lockscreen_mute_unmute_label">Sound</string>
<!-- A format string for 12-hour time of day, just the hour, not the minute, with lower-case "am" or "pm" (example: "3pm"). -->
<string name="hour_ampm">"<xliff:g id="hour" example="3">%-l</xliff:g><xliff:g id="ampm" example="pm">%P</xliff:g>"</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 6e38138..a629bb2 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -676,6 +676,25 @@
<style name="TextAppearance.Widget.TextView.SpinnerItem">
<item name="android:textColor">@android:color/primary_text_light_disable_only</item>
</style>
+
+ <!-- @hide -->
+ <style name="TextAppearance.SlidingTabNormal"
+ parent="@android:attr/textAppearanceMedium">
+ <item name="android:textColor">?android:attr/textColorTertiary</item>
+ <item name="android:textSize">28sp</item>
+ <item name="android:shadowColor">@android:color/sliding_tab_text_color_shadow</item>
+ <item name="android:shadowDx">0.0</item>
+ <item name="android:shadowDy">1.0</item>
+ <item name="android:shadowRadius">5.0</item>
+ </style>
+
+ <!-- @hide -->
+ <style name="TextAppearance.SlidingTabActive"
+ parent="@android:attr/textAppearanceMedium">
+ <item name="android:textColor">@android:color/sliding_tab_text_color_active</item>
+ <item name="android:textSize">28sp</item>
+ </style>
+
<!-- @hide -->
<style name="TextAppearance.SearchResult">