diff options
20 files changed, 1439 insertions, 18 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index cd1fbf6..12a8ff6 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -612,6 +612,13 @@ public class Notification implements Parcelable public static final String EXTRA_AS_HEADS_UP = "headsup"; /** + * Extra added from {@link Notification.Builder} to indicate that the remote views were inflated + * from the builder, as opposed to being created directly from the application. + * @hide + */ + public static final String EXTRA_BUILDER_REMOTE_VIEWS = "android.builderRemoteViews"; + + /** * Value for {@link #EXTRA_AS_HEADS_UP}. * @hide */ @@ -1273,6 +1280,7 @@ public class Notification implements Parcelable private boolean mShowWhen = true; private int mVisibility = VISIBILITY_PRIVATE; private Notification mPublicVersion = null; + private boolean mQuantumTheme; /** * Constructs a new Builder with the defaults: @@ -1300,6 +1308,9 @@ public class Notification implements Parcelable mWhen = System.currentTimeMillis(); mAudioStreamType = STREAM_DEFAULT; mPriority = PRIORITY_DEFAULT; + + // TODO: Decide on targetSdk from calling app whether to use quantum theme. + mQuantumTheme = true; } /** @@ -1807,7 +1818,7 @@ public class Notification implements Parcelable contentView.setImageViewBitmap(R.id.icon, mLargeIcon); smallIconImageViewId = R.id.right_icon; } - if (mPriority < PRIORITY_LOW) { + if (!mQuantumTheme && mPriority < PRIORITY_LOW) { contentView.setInt(R.id.icon, "setBackgroundResource", R.drawable.notification_template_icon_low_bg); contentView.setInt(R.id.status_bar_latest_event_content, @@ -1921,7 +1932,7 @@ public class Notification implements Parcelable if (mContentView != null) { return mContentView; } else { - return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor + return applyStandardTemplate(getBaseLayoutResource(), true); // no more special large_icon flavor } } @@ -1942,21 +1953,21 @@ public class Notification implements Parcelable private RemoteViews makeBigContentView() { if (mActions.size() == 0) return null; - return applyStandardTemplateWithActions(R.layout.notification_template_big_base); + return applyStandardTemplateWithActions(getBigBaseLayoutResource()); } - private RemoteViews makeHEadsUpContentView() { + private RemoteViews makeHeadsUpContentView() { if (mActions.size() == 0) return null; - return applyStandardTemplateWithActions(R.layout.notification_template_big_base); + return applyStandardTemplateWithActions(getBigBaseLayoutResource()); } private RemoteViews generateActionButton(Action action) { final boolean tombstone = (action.actionIntent == null); RemoteViews button = new RemoteViews(mContext.getPackageName(), - tombstone ? R.layout.notification_action_tombstone - : R.layout.notification_action); + tombstone ? getActionTombstoneLayoutResource() + : getActionLayoutResource()); button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0); button.setTextViewText(R.id.action0, action.title); if (!tombstone) { @@ -1992,7 +2003,7 @@ public class Notification implements Parcelable n.defaults = mDefaults; n.flags = mFlags; n.bigContentView = makeBigContentView(); - n.headsUpContentView = makeHEadsUpContentView(); + n.headsUpContentView = makeHeadsUpContentView(); if (mLedOnMs != 0 || mLedOffMs != 0) { n.flags |= FLAG_SHOW_LIGHTS; } @@ -2037,6 +2048,7 @@ public class Notification implements Parcelable extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate); extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer); extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen); + extras.putBoolean(EXTRA_BUILDER_REMOTE_VIEWS, mContentView == null); if (mLargeIcon != null) { extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon); } @@ -2080,6 +2092,49 @@ public class Notification implements Parcelable build().cloneInto(n, true); return n; } + + + private int getBaseLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_base + : R.layout.notification_template_base; + } + + private int getBigBaseLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_big_base + : R.layout.notification_template_big_base; + } + + private int getBigPictureLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_big_picture + : R.layout.notification_template_big_picture; + } + + private int getBigTextLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_big_text + : R.layout.notification_template_big_text; + } + + private int getInboxLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_inbox + : R.layout.notification_template_inbox; + } + + private int getActionLayoutResource() { + return mQuantumTheme + ? R.layout.notification_quantum_action + : R.layout.notification_action; + } + + private int getActionTombstoneLayoutResource() { + return mQuantumTheme + ? R.layout.notification_quantum_action_tombstone + : R.layout.notification_action_tombstone; + } } /** @@ -2249,7 +2304,7 @@ public class Notification implements Parcelable } private RemoteViews makeBigContentView() { - RemoteViews contentView = getStandardView(R.layout.notification_template_big_picture); + RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource()); contentView.setImageViewBitmap(R.id.big_picture, mPicture); @@ -2348,7 +2403,7 @@ public class Notification implements Parcelable final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null); mBuilder.mContentText = null; - RemoteViews contentView = getStandardView(R.layout.notification_template_big_text); + RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource()); if (hadThreeLines) { // vertical centering @@ -2442,7 +2497,7 @@ public class Notification implements Parcelable private RemoteViews makeBigContentView() { // Remove the content text so line3 disappears unless you have a summary mBuilder.mContentText = null; - RemoteViews contentView = getStandardView(R.layout.notification_template_inbox); + RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource()); contentView.setViewVisibility(R.id.text2, View.GONE); diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 2893522..419abf2 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -315,6 +315,24 @@ public class ColorStateList implements Parcelable { return mDefaultColor; } + /** + * Return the states in this {@link ColorStateList}. + * @return the states in this {@link ColorStateList} + * @hide + */ + public int[][] getStates() { + return mStateSpecs; + } + + /** + * Return the colors in this {@link ColorStateList}. + * @return the colors in this {@link ColorStateList} + * @hide + */ + public int[] getColors() { + return mColors; + } + @Override public String toString() { return "ColorStateList{" + diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_background.xml new file mode 100644 index 0000000..f33e2e3 --- /dev/null +++ b/core/res/res/drawable/notification_quantum_background.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#ffffffff" /> + <corners android:radius="2dp" /> +</shape>
\ No newline at end of file diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml new file mode 100644 index 0000000..608115e --- /dev/null +++ b/core/res/res/drawable/notification_quantum_bg.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" android:drawable="@drawable/notification_quantum_press" /> + <item android:state_pressed="false" android:drawable="@drawable/notification_quantum_background" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/drawable/notification_quantum_press.xml new file mode 100644 index 0000000..4999f55 --- /dev/null +++ b/core/res/res/drawable/notification_quantum_press.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#ffcccccc" /> + <corners android:radius="2dp" /> +</shape>
\ No newline at end of file diff --git a/core/res/res/layout/notification_quantum_action.xml b/core/res/res/layout/notification_quantum_action.xml new file mode 100644 index 0000000..775182f --- /dev/null +++ b/core/res/res/layout/notification_quantum_action.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<Button xmlns:android="http://schemas.android.com/apk/res/android" + style="?android:attr/borderlessButtonStyle" + android:id="@+id/action0" + android:layout_width="0dp" + android:layout_height="48dp" + android:layout_weight="1" + android:gravity="start|center_vertical" + android:drawablePadding="8dp" + android:paddingStart="8dp" + android:textColor="#555555" + android:textSize="14dp" + android:singleLine="true" + android:ellipsize="end" + /> diff --git a/core/res/res/layout/notification_quantum_action_list.xml b/core/res/res/layout/notification_quantum_action_list.xml new file mode 100644 index 0000000..a8aef97 --- /dev/null +++ b/core/res/res/layout/notification_quantum_action_list.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/actions" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:visibility="gone" + android:layout_marginBottom="8dp" + android:showDividers="middle" + android:divider="?android:attr/listDivider" + android:dividerPadding="12dp" + > + <!-- actions will be added here --> +</LinearLayout> diff --git a/core/res/res/layout/notification_quantum_action_tombstone.xml b/core/res/res/layout/notification_quantum_action_tombstone.xml new file mode 100644 index 0000000..9104991 --- /dev/null +++ b/core/res/res/layout/notification_quantum_action_tombstone.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<Button xmlns:android="http://schemas.android.com/apk/res/android" + style="?android:attr/borderlessButtonStyle" + android:id="@+id/action0" + android:layout_width="0dp" + android:layout_height="48dp" + android:layout_weight="1" + android:gravity="start|center_vertical" + android:drawablePadding="8dp" + android:paddingStart="8dp" + android:textColor="#555555" + android:textSize="14dp" + android:singleLine="true" + android:ellipsize="end" + android:alpha="0.5" + android:enabled="false" + /> diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml new file mode 100644 index 0000000..3e97b2a --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_base.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="64dp" + internal:layout_minHeight="64dp" + internal:layout_maxHeight="64dp" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + + android:layout_gravity="fill_vertical" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:paddingEnd="8dp" + android:paddingTop="2dp" + android:paddingBottom="2dp" + android:gravity="top" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="6dp" + android:layout_marginStart="8dp" + android:orientation="horizontal" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginStart="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:visibility="gone" + /> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginStart="8dp" + android:visibility="gone" + style="?android:attr/progressBarStyleHorizontal" + /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_marginStart="8dp" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml new file mode 100644 index 0000000..d860045 --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_big_base.xml @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:gravity="top" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:minHeight="@dimen/notification_large_icon_height" + android:paddingTop="2dp" + android:orientation="vertical" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="6dp" + android:layout_marginEnd="8dp" + android:layout_marginStart="8dp" + android:orientation="horizontal" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:visibility="gone" + /> + <TextView android:id="@+id/big_text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="false" + android:visibility="gone" + /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:orientation="horizontal" + android:gravity="center_vertical" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginBottom="8dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:visibility="gone" + style="?android:attr/progressBarStyleHorizontal" + /> + </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dp" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> + <include + layout="@layout/notification_quantum_action_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_large_icon_width" + /> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_big_picture.xml b/core/res/res/layout/notification_template_quantum_big_picture.xml new file mode 100644 index 0000000..e49c3bd --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_big_picture.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="match_parent" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView + android:id="@+id/big_picture" + android:layout_width="match_parent" + android:layout_height="192dp" + android:layout_marginTop="64dp" + android:layout_gravity="bottom" + android:scaleType="centerCrop" + /> + <ImageView + android:layout_width="match_parent" + android:layout_height="6dp" + android:layout_marginTop="64dp" + android:scaleType="fitXY" + android:src="@drawable/title_bar_shadow" + /> + <include layout="@layout/notification_template_quantum_base" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="208dp" + android:paddingStart="64dp" + android:layout_gravity="bottom" + android:background="#CCEEEEEE" + > + <include + layout="@layout/notification_quantum_action_list" + android:id="@+id/actions" + android:layout_gravity="bottom" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> + </FrameLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml new file mode 100644 index 0000000..585be80 --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_big_text.xml @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:orientation="vertical" + android:paddingTop="0dp" + android:paddingBottom="2dp" + android:gravity="top" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:layout_weight="1" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="8dp" + android:orientation="horizontal" + android:layout_gravity="top" + android:layout_weight="0" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:layout_weight="0" + android:visibility="gone" + /> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginBottom="8dp" + android:layout_marginEnd="8dp" + android:visibility="gone" + android:layout_weight="0" + style="?android:attr/progressBarStyleHorizontal" + /> + <TextView android:id="@+id/big_text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginBottom="10dp" + android:layout_marginEnd="8dp" + android:singleLine="false" + android:visibility="gone" + android:maxLines="8" + android:ellipsize="end" + android:layout_weight="1" + /> + </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> + <include + layout="@layout/notification_quantum_action_list" + android:layout_width="match_parent" + android:layout_height="0dp" + android:visibility="gone" + android:layout_weight="1" + /> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dp" + android:id="@+id/overflow_divider" + android:layout_marginBottom="8dp" + android:visibility="visible" + android:background="?android:attr/dividerHorizontal" /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginBottom="8dp" + android:layout_marginEnd="8dp" + android:orientation="horizontal" + android:layout_weight="0" + android:gravity="center_vertical" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml new file mode 100644 index 0000000..31ed508 --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_inbox.xml @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:id="@+id/status_bar_latest_event_content" + android:background="@android:drawable/notification_quantum_bg" + android:layout_width="match_parent" + android:layout_height="wrap_content" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:paddingTop="0dp" + android:paddingBottom="2dp" + android:gravity="top" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/notification_large_icon_height" + android:paddingTop="2dp" + android:orientation="vertical" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:paddingTop="6dp" + android:orientation="horizontal" + android:layout_weight="0" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:visibility="gone" + android:layout_weight="0" + /> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:visibility="gone" + android:layout_weight="0" + style="?android:attr/progressBarStyleHorizontal" + /> + <TextView android:id="@+id/inbox_text0" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text1" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text3" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text4" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text5" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text6" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_more" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + android:text="@android:string/ellipsis" + /> + <FrameLayout + android:id="@+id/inbox_end_pad" + android:layout_width="match_parent" + android:layout_height="8dip" + android:visibility="gone" + android:layout_weight="0" + /> + </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> + <include + layout="@layout/notification_quantum_action_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="0" + /> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:id="@+id/overflow_divider" + android:visibility="visible" + android:background="?android:attr/dividerHorizontal" /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginStart="8dp" + android:layout_marginBottom="8dp" + android:layout_marginEnd="8dp" + android:orientation="horizontal" + android:layout_weight="0" + android:gravity="center_vertical" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index e525ef7..be875ff 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -271,6 +271,33 @@ please see styles_device_defaults.xml. <item name="android:textColor">#CCCCCC</item> </style> + <style name="TextAppearance.StatusBar.Quantum"> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent"> + <item name="android:textColor">#888888</item> + <item name="android:textSize">@dimen/notification_text_size</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Title"> + <item name="android:textColor">#000000</item> + <item name="android:fontFamily">sans-serif-light</item> + <item name="android:textSize">@dimen/notification_title_text_size</item> + <item name="android:textStyle">bold</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Line2"> + <item name="android:textSize">@dimen/notification_subtext_size</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Info"> + <item name="android:textSize">@dimen/notification_subtext_size</item> + <item name="android:textColor">#888888</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Time"> + <item name="android:textSize">@dimen/notification_subtext_size</item> + <item name="android:textColor">#888888</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Emphasis"> + <item name="android:textColor">#555555</item> + </style> + <style name="TextAppearance.Small.CalendarViewWeekDayView"> <item name="android:textStyle">bold</item> </style> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a4f9762..3a45d8c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1627,7 +1627,16 @@ <java-symbol type="integer" name="config_maxResolverActivityColumns" /> <java-symbol type="array" name="config_notificationScorers" /> - <!-- From SystemUI --> + <java-symbol type="layout" name="notification_quantum_action" /> + <java-symbol type="layout" name="notification_quantum_action_list" /> + <java-symbol type="layout" name="notification_quantum_action_tombstone" /> + <java-symbol type="layout" name="notification_template_quantum_base" /> + <java-symbol type="layout" name="notification_template_quantum_big_base" /> + <java-symbol type="layout" name="notification_template_quantum_big_picture" /> + <java-symbol type="layout" name="notification_template_quantum_big_text" /> + <java-symbol type="layout" name="notification_template_quantum_inbox" /> + + <!-- From SystemUI --> <java-symbol type="anim" name="push_down_in" /> <java-symbol type="anim" name="push_down_out" /> <java-symbol type="anim" name="push_up_in" /> diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml new file mode 100644 index 0000000..4ac67c3 --- /dev/null +++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <solid + android:color="@color/notification_icon_legacy_bg_color"/> +</shape> diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml new file mode 100644 index 0000000..96c5573 --- /dev/null +++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/notification_icon_legacy_bg" android:insetBottom="8dp" + android:insetLeft="8dp" android:insetRight="8dp" android:insetTop="8dp" + android:visible="true"/> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 5cf0453..a59dc75 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -39,6 +39,8 @@ <color name="status_bar_clock_color">#FFFFFFFF</color> <drawable name="notification_item_background_color">#ff111111</drawable> <drawable name="notification_item_background_color_pressed">#ff454545</drawable> + <color name="notification_icon_legacy_bg_color">#ff4285F4</color> + <color name="notification_action_legacy_color_filter">#ff555555</color> <!-- Tint color for inactive Quick Settings icons. --> <color name="ic_qs_off">#ff404040</color> diff --git a/packages/SystemUI/src/com/android/systemui/ImageUtils.java b/packages/SystemUI/src/com/android/systemui/ImageUtils.java new file mode 100644 index 0000000..540ba20 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ImageUtils.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014 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.systemui; + +import android.graphics.Bitmap; + +/** + * Utility class for image analysis and processing. + */ +public class ImageUtils { + + // Amount (max is 255) that two channels can differ before the color is no longer "gray". + private static final int TOLERANCE = 20; + + // Alpha amount for which values below are considered transparent. + private static final int ALPHA_TOLERANCE = 50; + + private int[] mTempBuffer; + + /** + * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect + * gray". + */ + public boolean isGrayscale(Bitmap bitmap) { + final int height = bitmap.getHeight(); + final int width = bitmap.getWidth(); + int size = height*width; + + ensureBufferSize(size); + bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height); + for (int i = 0; i < size; i++) { + if (!isGrayscale(mTempBuffer[i])) { + return false; + } + } + return true; + } + + /** + * Makes sure that {@code mTempBuffer} has at least length {@code size}. + */ + private void ensureBufferSize(int size) { + if (mTempBuffer == null || mTempBuffer.length < size) { + mTempBuffer = new int[size]; + } + } + + /** + * Classifies a color as grayscale or not. Grayscale here means "very close to a perfect + * gray"; if all three channels are approximately equal, this will return true. + * + * Note that really transparent colors are always grayscale. + */ + public boolean isGrayscale(int color) { + int alpha = 0xFF & (color >> 24); + if (alpha < ALPHA_TOLERANCE) { + return true; + } + + int r = 0xFF & (color >> 16); + int g = 0xFF & (color >> 8); + int b = 0xFF & color; + + return Math.abs(r - g) < TOLERANCE + && Math.abs(r - b) < TOLERANCE + && Math.abs(g - b) < TOLERANCE; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index fb11743..eb07d88 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -28,9 +28,15 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.database.ContentObserver; +import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.Rect; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Handler; @@ -44,9 +50,13 @@ import android.provider.Settings; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.TextAppearanceSpan; import android.util.Log; import android.util.SparseBooleanArray; +import android.view.ContextThemeWrapper; import android.view.Display; import android.view.IWindowManager; import android.view.LayoutInflater; @@ -57,6 +67,7 @@ import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupMenu; @@ -67,6 +78,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIconList; import com.android.internal.widget.SizeAdaptiveLayout; +import com.android.systemui.ImageUtils; import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SearchPanelView; @@ -76,6 +88,7 @@ import com.android.systemui.statusbar.policy.NotificationRowLayout; import java.util.ArrayList; import java.util.Locale; +import java.util.Stack; public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks { @@ -140,6 +153,8 @@ public abstract class BaseStatusBar extends SystemUI implements // public mode, private notifications, etc private boolean mLockscreenPublicMode = false; private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray(); + private Context mLightThemeContext; + private ImageUtils mImageUtils = new ImageUtils(); // UI-specific methods @@ -261,6 +276,8 @@ public abstract class BaseStatusBar extends SystemUI implements true, mLockscreenSettingsObserver, UserHandle.USER_ALL); + mLightThemeContext = new RemoteViewsThemeContextWrapper(mContext, + android.R.style.Theme_Holo_Light); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); @@ -412,6 +429,158 @@ public abstract class BaseStatusBar extends SystemUI implements } } + private void processLegacyHoloNotification(StatusBarNotification sbn, View content) { + + // TODO: Also skip processing if it is a holo-style notification. + // If the notification is custom, we can't process it. + if (!sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) { + return; + } + + processLegacyHoloLargeIcon(content); + processLegacyHoloActions(content); + processLegacyNotificationIcon(content); + processLegacyTextViews(content); + } + + /** + * @return the context to be used for the inflation of the specified {@code sbn}; this is + * dependent whether the notification is quantum-style or holo-style + */ + private Context getInflationContext(StatusBarNotification sbn) { + + // TODO: Adjust this logic when we change the theme of the status bar windows. + if (sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) { + return mLightThemeContext; + } else { + return mContext; + } + } + + private void processLegacyNotificationIcon(View content) { + View v = content.findViewById(com.android.internal.R.id.right_icon); + if (v != null & v instanceof ImageView) { + ImageView iv = (ImageView) v; + Drawable d = iv.getDrawable(); + if (isMonochrome(d)) { + d.mutate(); + d.setColorFilter(mLightThemeContext.getResources().getColor( + R.color.notification_action_legacy_color_filter), PorterDuff.Mode.MULTIPLY); + } + } + } + + private void processLegacyHoloLargeIcon(View content) { + View v = content.findViewById(com.android.internal.R.id.icon); + if (v != null & v instanceof ImageView) { + ImageView iv = (ImageView) v; + if (isMonochrome(iv.getDrawable())) { + iv.setBackground(mLightThemeContext.getResources().getDrawable( + R.drawable.notification_icon_legacy_bg_inset)); + } + } + } + + private boolean isMonochrome(Drawable d) { + if (d == null) { + return false; + } else if (d instanceof BitmapDrawable) { + BitmapDrawable bd = (BitmapDrawable) d; + return bd.getBitmap() != null && mImageUtils.isGrayscale(bd.getBitmap()); + } else if (d instanceof AnimationDrawable) { + AnimationDrawable ad = (AnimationDrawable) d; + int count = ad.getNumberOfFrames(); + return count > 0 && isMonochrome(ad.getFrame(0)); + } else { + return false; + } + } + + private void processLegacyHoloActions(View content) { + View v = content.findViewById(com.android.internal.R.id.actions); + if (v != null & v instanceof ViewGroup) { + ViewGroup vg = (ViewGroup) v; + int childCount = vg.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = vg.getChildAt(i); + if (child instanceof Button) { + Button button = (Button) child; + Drawable[] compoundDrawables = button.getCompoundDrawablesRelative(); + if (isMonochrome(compoundDrawables[0])) { + Drawable d = compoundDrawables[0]; + d.mutate(); + d.setColorFilter(mLightThemeContext.getResources().getColor( + R.color.notification_action_legacy_color_filter), + PorterDuff.Mode.MULTIPLY); + } + } + } + } + } + + private void processLegacyTextViews(View content) { + Stack<View> viewStack = new Stack<View>(); + viewStack.push(content); + while(!viewStack.isEmpty()) { + View current = viewStack.pop(); + if(current instanceof ViewGroup){ + ViewGroup currentGroup = (ViewGroup) current; + int numChildren = currentGroup.getChildCount(); + for(int i=0;i<numChildren;i++){ + viewStack.push(currentGroup.getChildAt(i)); + } + } + if (current instanceof TextView) { + processLegacyTextView((TextView) current); + } + } + } + + private void processLegacyTextView(TextView textView) { + if (textView.getText() instanceof Spanned) { + Spanned ss = (Spanned) textView.getText(); + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); + for (Object span : spans) { + Object resultSpan = span; + if (span instanceof TextAppearanceSpan) { + resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span); + } + builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span), + ss.getSpanFlags(span)); + } + textView.setText(builder); + } + } + + private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) { + ColorStateList colorStateList = span.getTextColor(); + if (colorStateList != null) { + int[] colors = colorStateList.getColors(); + boolean changed = false; + for (int i = 0; i < colors.length; i++) { + if (mImageUtils.isGrayscale(colors[i])) { + colors[i] = processColor(colors[i]); + changed = true; + } + } + if (changed) { + return new TextAppearanceSpan( + span.getFamily(), span.getTextStyle(), span.getTextSize(), + new ColorStateList(colorStateList.getStates(), colors), + span.getLinkTextColor()); + } + } + return span; + } + + private int processColor(int color) { + return Color.argb(Color.alpha(color), + 255 - Color.red(color), + 255 - Color.green(color), + 255 - Color.blue(color)); + } + private void startApplicationDetailsActivity(String packageName) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", packageName, null)); @@ -748,9 +917,11 @@ public abstract class BaseStatusBar extends SystemUI implements View contentViewLocal = null; View bigContentViewLocal = null; try { - contentViewLocal = contentView.apply(mContext, expanded, mOnClickHandler); + contentViewLocal = contentView.apply(getInflationContext(sbn), expanded, + mOnClickHandler); if (bigContentView != null) { - bigContentViewLocal = bigContentView.apply(mContext, expanded, mOnClickHandler); + bigContentViewLocal = bigContentView.apply(getInflationContext(sbn), expanded, + mOnClickHandler); } } catch (RuntimeException e) { @@ -780,7 +951,7 @@ public abstract class BaseStatusBar extends SystemUI implements View publicViewLocal = null; if (publicNotification != null) { try { - publicViewLocal = publicNotification.contentView.apply(mContext, + publicViewLocal = publicNotification.contentView.apply(getInflationContext(sbn), expandedPublic, mOnClickHandler); if (publicViewLocal != null) { @@ -831,6 +1002,13 @@ public abstract class BaseStatusBar extends SystemUI implements row.setDrawingCacheEnabled(true); applyLegacyRowBackground(sbn, content); + processLegacyHoloNotification(sbn, contentViewLocal); + if (bigContentViewLocal != null) { + processLegacyHoloNotification(sbn, bigContentViewLocal); + } + if (publicViewLocal != null) { + processLegacyHoloNotification(sbn, publicViewLocal); + } if (MULTIUSER_DEBUG) { TextView debug = (TextView) row.findViewById(R.id.debug_info); @@ -1245,12 +1423,17 @@ public abstract class BaseStatusBar extends SystemUI implements : null; // Reapply the RemoteViews - contentView.reapply(mContext, entry.expanded, mOnClickHandler); + contentView.reapply(getInflationContext(notification), entry.expanded, mOnClickHandler); + processLegacyHoloNotification(notification, entry.expanded); if (bigContentView != null && entry.getBigContentView() != null) { - bigContentView.reapply(mContext, entry.getBigContentView(), mOnClickHandler); + bigContentView.reapply(getInflationContext(notification), entry.getBigContentView(), + mOnClickHandler); + processLegacyHoloNotification(notification, entry.getBigContentView()); } if (publicContentView != null && entry.getPublicContentView() != null) { - publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler); + publicContentView.reapply(getInflationContext(notification), + entry.getPublicContentView(), mOnClickHandler); + processLegacyHoloNotification(notification, entry.getPublicContentView()); } // update the contentIntent final PendingIntent contentIntent = notification.getNotification().contentIntent; @@ -1330,4 +1513,35 @@ public abstract class BaseStatusBar extends SystemUI implements } mContext.unregisterReceiver(mBroadcastReceiver); } + + /** + * A custom context theme wrapper that applies a platform theme to a created package context. + * This is useful if you want to inflate {@link RemoteViews} with a custom theme (normally, the + * theme used there is the default platform theme). + */ + private static class RemoteViewsThemeContextWrapper extends ContextThemeWrapper { + + private int mThemeRes; + + private RemoteViewsThemeContextWrapper(Context base, int themeres) { + super(base, themeres); + mThemeRes = themeres; + } + + @Override + public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) + throws NameNotFoundException { + Context c = super.createPackageContextAsUser(packageName, flags, user); + c.setTheme(mThemeRes); + return c; + } + + @Override + public Context createPackageContext(String packageName, int flags) + throws NameNotFoundException { + Context c = super.createPackageContext(packageName, flags); + c.setTheme(mThemeRes); + return c; + } + } } |