diff options
author | Dan Sandler <dsandler@android.com> | 2019-06-26 01:01:26 -0400 |
---|---|---|
committer | Dan Sandler <dsandler@android.com> | 2019-07-10 15:51:12 -0400 |
commit | a7613376379947f463a34543358e535fc28e30eb (patch) | |
tree | 16cc14ce417c3d242ae94d52bc8d1b6321f8493c /packages/EasterEgg | |
parent | 99367a7ba08aac635fd69ce50d8505cde7e04e44 (diff) |
Q card.
(Goodbye, hypno-P and your '90s tech magazine color palette.)
Bug: 123903304
Test: adb shell am start -n android/com.android.internal.app.PlatLogoActivity
Test: adb shell am start -c com.android.internal.category.PLATLOGO -a android.intent.action.MAIN
Test: adb shell am start -n com.android.egg/.paint.PaintActivity # still works
Change-Id: I4865024a14b6a78e7a043c56d2330b5f9dd214c6
Diffstat (limited to 'packages/EasterEgg')
-rw-r--r-- | packages/EasterEgg/AndroidManifest.xml | 40 | ||||
-rw-r--r-- | packages/EasterEgg/res/drawable/icon_bg.xml | 2 | ||||
-rw-r--r-- | packages/EasterEgg/res/drawable/p_icon.xml (renamed from packages/EasterEgg/res/drawable/icon.xml) | 0 | ||||
-rw-r--r-- | packages/EasterEgg/res/drawable/pixel_bg.xml | 27 | ||||
-rw-r--r-- | packages/EasterEgg/res/drawable/q.xml | 27 | ||||
-rw-r--r-- | packages/EasterEgg/res/drawable/q_icon.xml | 19 | ||||
-rw-r--r-- | packages/EasterEgg/res/drawable/q_smaller.xml | 23 | ||||
-rw-r--r-- | packages/EasterEgg/res/layout/activity_quares.xml | 46 | ||||
-rw-r--r-- | packages/EasterEgg/res/values-night/q_colors.xml | 22 | ||||
-rw-r--r-- | packages/EasterEgg/res/values/q_colors.xml | 31 | ||||
-rw-r--r-- | packages/EasterEgg/res/values/q_puzzles.xml | 214 | ||||
-rw-r--r-- | packages/EasterEgg/res/values/strings.xml | 11 | ||||
-rw-r--r-- | packages/EasterEgg/res/values/styles.xml | 12 | ||||
-rw-r--r-- | packages/EasterEgg/src/com/android/egg/quares/Quare.kt | 168 | ||||
-rw-r--r-- | packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt | 312 |
15 files changed, 929 insertions, 25 deletions
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml index c7dd40d7afdb..7f76a4529963 100644 --- a/packages/EasterEgg/AndroidManifest.xml +++ b/packages/EasterEgg/AndroidManifest.xml @@ -1,40 +1,38 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2018 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. ---> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.egg" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="28" /> + <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <application - android:icon="@drawable/icon" + android:icon="@drawable/q_icon" android:label="@string/app_name"> + <activity android:name=".quares.QuaresActivity" + android:icon="@drawable/q_icon" + android:label="@string/q_egg_name" + android:theme="@style/QuaresTheme"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <!-- <category android:name="android.intent.category.LAUNCHER" /> --> + <category android:name="com.android.internal.category.PLATLOGO" /> + </intent-filter> + </activity> <activity android:name=".paint.PaintActivity" android:configChanges="orientation|keyboardHidden|screenSize|uiMode" - android:label="@string/app_name" + android:icon="@drawable/p_icon" + android:label="@string/p_egg_name" android:theme="@style/AppTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.DEFAULT" /> - <!--<category android:name="android.intent.category.LAUNCHER" />--> - <category android:name="com.android.internal.category.PLATLOGO" /> + + <!-- <category android:name="android.intent.category.DEFAULT" /> --> + <!-- <category android:name="android.intent.category.LAUNCHER" /> --> + <!-- <category android:name="com.android.internal.category.PLATLOGO" /> --> </intent-filter> </activity> </application> diff --git a/packages/EasterEgg/res/drawable/icon_bg.xml b/packages/EasterEgg/res/drawable/icon_bg.xml index c1553ce50946..659f98be4f43 100644 --- a/packages/EasterEgg/res/drawable/icon_bg.xml +++ b/packages/EasterEgg/res/drawable/icon_bg.xml @@ -15,4 +15,4 @@ limitations under the License. --> <color xmlns:android="http://schemas.android.com/apk/res/android" - android:color="#C5E1A5" />
\ No newline at end of file + android:color="@color/q_clue_text" /> diff --git a/packages/EasterEgg/res/drawable/icon.xml b/packages/EasterEgg/res/drawable/p_icon.xml index 2306b7b554c5..2306b7b554c5 100644 --- a/packages/EasterEgg/res/drawable/icon.xml +++ b/packages/EasterEgg/res/drawable/p_icon.xml diff --git a/packages/EasterEgg/res/drawable/pixel_bg.xml b/packages/EasterEgg/res/drawable/pixel_bg.xml new file mode 100644 index 000000000000..4d4a113cce53 --- /dev/null +++ b/packages/EasterEgg/res/drawable/pixel_bg.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 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" + android:exitFadeDuration="100"> + <item android:state_pressed="true"> + <shape><solid android:color="@color/red"/></shape> + </item> + <item android:state_checked="true"> + <shape><solid android:color="@color/pixel_on"/></shape> + </item> + <item> + <shape><solid android:color="@color/pixel_off"/></shape> + </item> +</selector>
\ No newline at end of file diff --git a/packages/EasterEgg/res/drawable/q.xml b/packages/EasterEgg/res/drawable/q.xml new file mode 100644 index 000000000000..75baa47e3aa6 --- /dev/null +++ b/packages/EasterEgg/res/drawable/q.xml @@ -0,0 +1,27 @@ +<!-- +Copyright (C) 2015 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="@color/q_icon_fg" + android:pathData="M19.45,22.89l-10.250001,-10.249999l-2.6599998,2.6599998l-1.77,-1.7600002l4.43,-4.4300003l12.0199995,12.0199995l-1.7699986,1.7600002z"/> + <path + android:fillColor="@color/q_icon_fg" + android:pathData="M12,6a6,6 0,1 1,-6 6,6 6,0 0,1 6,-6m0,-2.5A8.5,8.5 0,1 0,20.5 12,8.51 8.51,0 0,0 12,3.5Z"/> +</vector> diff --git a/packages/EasterEgg/res/drawable/q_icon.xml b/packages/EasterEgg/res/drawable/q_icon.xml new file mode 100644 index 000000000000..ef4b0a362043 --- /dev/null +++ b/packages/EasterEgg/res/drawable/q_icon.xml @@ -0,0 +1,19 @@ +<!-- + Copyright (C) 2019 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. +--> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/icon_bg"/> + <foreground android:drawable="@drawable/q_smaller"/> +</adaptive-icon> diff --git a/packages/EasterEgg/res/drawable/q_smaller.xml b/packages/EasterEgg/res/drawable/q_smaller.xml new file mode 100644 index 000000000000..c71dff094235 --- /dev/null +++ b/packages/EasterEgg/res/drawable/q_smaller.xml @@ -0,0 +1,23 @@ +<!-- +Copyright (C) 2019 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:width="24dp" + android:height="24dp" + android:insetBottom="5dp" + android:insetLeft="5dp" + android:insetRight="5dp" + android:insetTop="5dp" + android:drawable="@drawable/q" /> diff --git a/packages/EasterEgg/res/layout/activity_quares.xml b/packages/EasterEgg/res/layout/activity_quares.xml new file mode 100644 index 000000000000..dcc90f6f77ae --- /dev/null +++ b/packages/EasterEgg/res/layout/activity_quares.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 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:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:animateLayoutChanges="true" + tools:context="com.android.egg.quares.QuaresActivity"> + + <GridLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:alignmentMode="alignBounds" + android:id="@+id/grid" + /> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/label" + android:layout_gravity="center_horizontal|bottom" + android:gravity="center" + android:textSize="18dp" + android:visibility="gone" + android:drawablePadding="8dp" + android:padding="12dp" + android:backgroundTint="@color/q_clue_bg_correct" + android:textColor="@color/q_clue_text" + android:layout_marginBottom="48dp" + android:elevation="30dp" + /> +</FrameLayout> diff --git a/packages/EasterEgg/res/values-night/q_colors.xml b/packages/EasterEgg/res/values-night/q_colors.xml new file mode 100644 index 000000000000..191bd944b7dc --- /dev/null +++ b/packages/EasterEgg/res/values-night/q_colors.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 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. +--> +<resources> + <color name="pixel_off">#000000</color> + <color name="pixel_on">#FFFFFF</color> + + <color name="q_clue_bg">@color/navy</color> + <color name="q_clue_text">@color/tan</color> +</resources>
\ No newline at end of file diff --git a/packages/EasterEgg/res/values/q_colors.xml b/packages/EasterEgg/res/values/q_colors.xml new file mode 100644 index 000000000000..5e92c84fd97d --- /dev/null +++ b/packages/EasterEgg/res/values/q_colors.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 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. +--> +<resources> + <color name="emerald">#3ddc84</color> + <color name="red">#f8c734</color> + <color name="navy">#073042</color> + <color name="vapor">#d7effe</color> + <color name="tan">#eff7cf</color> + + <color name="pixel_off">#FFFFFF</color> + <color name="pixel_on">#000000</color> + + <color name="q_clue_bg">@color/tan</color> + <color name="q_clue_text">@color/navy</color> + <color name="q_clue_bg_correct">@color/emerald</color> + + <color name="q_icon_fg">@color/emerald</color> +</resources> diff --git a/packages/EasterEgg/res/values/q_puzzles.xml b/packages/EasterEgg/res/values/q_puzzles.xml new file mode 100644 index 000000000000..7c2eff152ffe --- /dev/null +++ b/packages/EasterEgg/res/values/q_puzzles.xml @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string-array name="puzzles"> + + <item>q</item> + <item>q</item> + <item>q</item> + <item>q</item> + <item>q</item> + + <item>android:drawable/ic_info</item> + + <item>android:drawable/stat_sys_adb</item> + <item>android:drawable/stat_sys_battery</item> + <item>android:drawable/stat_sys_phone_call</item> + <item>android:drawable/stat_sys_certificate_info</item> + <item>android:drawable/stat_sys_data_bluetooth</item> + <item>android:drawable/stat_sys_data_usb</item> + <item>android:drawable/stat_sys_download</item> + <item>android:drawable/stat_sys_gps_on</item> + <item>android:drawable/stat_sys_phone_call</item> + <item>android:drawable/stat_sys_tether_wifi</item> + <item>android:drawable/stat_sys_throttled</item> + <item>android:drawable/stat_sys_upload</item> + + <item>android:drawable/stat_notify_car_mode</item> + <item>android:drawable/stat_notify_chat</item> + <item>android:drawable/stat_notify_disk_full</item> + <item>android:drawable/stat_notify_email_generic</item> + <item>android:drawable/stat_notify_error</item> + <item>android:drawable/stat_notify_gmail</item> + <item>android:drawable/stat_notify_missed_call</item> + <item>android:drawable/stat_notify_mmcc_indication_icn</item> + <item>android:drawable/stat_notify_more</item> + <item>android:drawable/stat_notify_rssi_in_range</item> + <item>android:drawable/stat_notify_sdcard</item> + <item>android:drawable/stat_notify_sdcard_prepare</item> + <item>android:drawable/stat_notify_sdcard_usb</item> + <item>android:drawable/stat_notify_sim_toolkit</item> + <item>android:drawable/stat_notify_sync</item> + <item>android:drawable/stat_notify_sync_anim0</item> + <item>android:drawable/stat_notify_sync_error</item> + <item>android:drawable/stat_notify_voicemail</item> + + <item>android:drawable/ic_audio_alarm</item> + <item>android:drawable/ic_audio_alarm_mute</item> + <item>android:drawable/ic_bluetooth_share_icon</item> + <item>android:drawable/ic_bt_headphones_a2dp</item> + <item>android:drawable/ic_bt_headset_hfp</item> + <item>android:drawable/ic_bt_hearing_aid</item> + <item>android:drawable/ic_bt_laptop</item> + <item>android:drawable/ic_bt_misc_hid</item> + <item>android:drawable/ic_bt_network_pan</item> + <item>android:drawable/ic_bt_pointing_hid</item> + <item>android:drawable/ic_corp_badge</item> + <item>android:drawable/ic_expand_more</item> + <item>android:drawable/ic_faster_emergency</item> + <item>android:drawable/ic_file_copy</item> + <item>android:drawable/ic_info_outline_24</item> + <item>android:drawable/ic_lock</item> + <item>android:drawable/ic_lock_bugreport</item> + <item>android:drawable/ic_lock_open</item> + <item>android:drawable/ic_lock_power_off</item> + <item>android:drawable/ic_lockscreen_ime</item> + <item>android:drawable/ic_mode_edit</item> + <item>android:drawable/ic_phone</item> + <item>android:drawable/ic_qs_airplane</item> + <item>android:drawable/ic_qs_auto_rotate</item> + <item>android:drawable/ic_qs_battery_saver</item> + <item>android:drawable/ic_qs_bluetooth</item> + <item>android:drawable/ic_qs_dnd</item> + <item>android:drawable/ic_qs_flashlight</item> + <item>android:drawable/ic_qs_night_display_on</item> + <item>android:drawable/ic_restart</item> + <item>android:drawable/ic_screenshot</item> + <item>android:drawable/ic_settings_bluetooth</item> + <item>android:drawable/ic_signal_cellular_0_4_bar</item> + <item>android:drawable/ic_signal_cellular_0_5_bar</item> + <item>android:drawable/ic_signal_cellular_1_4_bar</item> + <item>android:drawable/ic_signal_cellular_1_5_bar</item> + <item>android:drawable/ic_signal_cellular_2_4_bar</item> + <item>android:drawable/ic_signal_cellular_2_5_bar</item> + <item>android:drawable/ic_signal_cellular_3_4_bar</item> + <item>android:drawable/ic_signal_cellular_3_5_bar</item> + <item>android:drawable/ic_signal_cellular_4_4_bar</item> + <item>android:drawable/ic_signal_cellular_4_5_bar</item> + <item>android:drawable/ic_signal_cellular_5_5_bar</item> + <item>android:drawable/ic_signal_location</item> + <item>android:drawable/ic_wifi_signal_0</item> + <item>android:drawable/ic_wifi_signal_1</item> + <item>android:drawable/ic_wifi_signal_2</item> + <item>android:drawable/ic_wifi_signal_3</item> + <item>android:drawable/ic_wifi_signal_4</item> + <item>android:drawable/perm_group_activity_recognition</item> + <item>android:drawable/perm_group_calendar</item> + <item>android:drawable/perm_group_call_log</item> + <item>android:drawable/perm_group_camera</item> + <item>android:drawable/perm_group_contacts</item> + <item>android:drawable/perm_group_location</item> + <item>android:drawable/perm_group_microphone</item> + <item>android:drawable/perm_group_phone_calls</item> + <item>android:drawable/perm_group_sensors</item> + <item>android:drawable/perm_group_sms</item> + <item>android:drawable/perm_group_storage</item> + <item>android:drawable/perm_group_visual</item> + + <item>com.android.settings:drawable/ic_add_24dp</item> + <item>com.android.settings:drawable/ic_airplanemode_active</item> + <item>com.android.settings:drawable/ic_android</item> + <item>com.android.settings:drawable/ic_apps</item> + <item>com.android.settings:drawable/ic_arrow_back</item> + <item>com.android.settings:drawable/ic_arrow_down_24dp</item> + <item>com.android.settings:drawable/ic_battery_charging_full</item> + <item>com.android.settings:drawable/ic_battery_status_bad_24dp</item> + <item>com.android.settings:drawable/ic_battery_status_good_24dp</item> + <item>com.android.settings:drawable/ic_battery_status_maybe_24dp</item> + <item>com.android.settings:drawable/ic_call_24dp</item> + <item>com.android.settings:drawable/ic_cancel</item> + <item>com.android.settings:drawable/ic_cast_24dp</item> + <item>com.android.settings:drawable/ic_chevron_right_24dp</item> + <item>com.android.settings:drawable/ic_data_saver</item> + <item>com.android.settings:drawable/ic_delete</item> + <item>com.android.settings:drawable/ic_devices_other</item> + <item>com.android.settings:drawable/ic_devices_other_opaque_black</item> + <item>com.android.settings:drawable/ic_do_not_disturb_on_24dp</item> + <item>com.android.settings:drawable/ic_eject_24dp</item> + <item>com.android.settings:drawable/ic_expand_less</item> + <item>com.android.settings:drawable/ic_expand_more_inverse</item> + <item>com.android.settings:drawable/ic_folder_vd_theme_24</item> + <item>com.android.settings:drawable/ic_friction_lock_closed</item> + <item>com.android.settings:drawable/ic_gray_scale_24dp</item> + <item>com.android.settings:drawable/ic_headset_24dp</item> + <item>com.android.settings:drawable/ic_help</item> + <item>com.android.settings:drawable/ic_local_movies</item> + <item>com.android.settings:drawable/ic_lock</item> + <item>com.android.settings:drawable/ic_media_stream</item> + <item>com.android.settings:drawable/ic_network_cell</item> + <item>com.android.settings:drawable/ic_notifications</item> + <item>com.android.settings:drawable/ic_notifications_off_24dp</item> + <item>com.android.settings:drawable/ic_phone_info</item> + <item>com.android.settings:drawable/ic_photo_library</item> + <item>com.android.settings:drawable/ic_settings_accessibility</item> + <item>com.android.settings:drawable/ic_settings_accounts</item> + <item>com.android.settings:drawable/ic_settings_backup</item> + <item>com.android.settings:drawable/ic_settings_battery_white</item> + <item>com.android.settings:drawable/ic_settings_data_usage</item> + <item>com.android.settings:drawable/ic_settings_date_time</item> + <item>com.android.settings:drawable/ic_settings_delete</item> + <item>com.android.settings:drawable/ic_settings_display_white</item> + <item>com.android.settings:drawable/ic_settings_home</item> + <item>com.android.settings:drawable/ic_settings_location</item> + <item>com.android.settings:drawable/ic_settings_night_display</item> + <item>com.android.settings:drawable/ic_settings_open</item> + <item>com.android.settings:drawable/ic_settings_print</item> + <item>com.android.settings:drawable/ic_settings_privacy</item> + <item>com.android.settings:drawable/ic_settings_security_white</item> + <item>com.android.settings:drawable/ic_settings_sim</item> + <item>com.android.settings:drawable/ic_settings_wireless</item> + <item>com.android.settings:drawable/ic_storage</item> + <item>com.android.settings:drawable/ic_storage_white</item> + <item>com.android.settings:drawable/ic_suggestion_night_display</item> + <item>com.android.settings:drawable/ic_sync</item> + <item>com.android.settings:drawable/ic_system_update</item> + <item>com.android.settings:drawable/ic_videogame_vd_theme_24</item> + <item>com.android.settings:drawable/ic_volume_ringer_vibrate</item> + <item>com.android.settings:drawable/ic_volume_up_24dp</item> + <item>com.android.settings:drawable/ic_vpn_key</item> + <item>com.android.settings:drawable/ic_wifi_tethering</item> + + <item>com.android.systemui:drawable/ic_alarm</item> + <item>com.android.systemui:drawable/ic_alarm_dim</item> + <item>com.android.systemui:drawable/ic_arrow_back</item> + <item>com.android.systemui:drawable/ic_bluetooth_connected</item> + <item>com.android.systemui:drawable/ic_brightness_thumb</item> + <item>com.android.systemui:drawable/ic_camera</item> + <item>com.android.systemui:drawable/ic_cast</item> + <item>com.android.systemui:drawable/ic_cast_connected</item> + <item>com.android.systemui:drawable/ic_cast_connected_fill</item> + <item>com.android.systemui:drawable/ic_close_white</item> + <item>com.android.systemui:drawable/ic_data_saver</item> + <item>com.android.systemui:drawable/ic_data_saver_off</item> + <item>com.android.systemui:drawable/ic_drag_handle</item> + <item>com.android.systemui:drawable/ic_headset</item> + <item>com.android.systemui:drawable/ic_headset_mic</item> + <item>com.android.systemui:drawable/ic_hotspot</item> + <item>com.android.systemui:drawable/ic_invert_colors</item> + <item>com.android.systemui:drawable/ic_location</item> + <item>com.android.systemui:drawable/ic_lockscreen_ime</item> + <item>com.android.systemui:drawable/ic_notifications_alert</item> + <item>com.android.systemui:drawable/ic_notifications_silence</item> + <item>com.android.systemui:drawable/ic_power_low</item> + <item>com.android.systemui:drawable/ic_power_saver</item> + <item>com.android.systemui:drawable/ic_qs_bluetooth_connecting</item> + <item>com.android.systemui:drawable/ic_qs_bluetooth_on</item> + <item>com.android.systemui:drawable/ic_qs_cancel</item> + <item>com.android.systemui:drawable/ic_qs_no_sim</item> + <item>com.android.systemui:drawable/ic_screenshot_delete</item> + <item>com.android.systemui:drawable/ic_settings</item> + <item>com.android.systemui:drawable/ic_swap_vert</item> + <item>com.android.systemui:drawable/ic_volume_alarm</item> + <item>com.android.systemui:drawable/ic_volume_alarm_mute</item> + <item>com.android.systemui:drawable/ic_volume_media</item> + <item>com.android.systemui:drawable/ic_volume_media_mute</item> + <item>com.android.systemui:drawable/ic_volume_ringer</item> + <item>com.android.systemui:drawable/ic_volume_ringer_mute</item> + <item>com.android.systemui:drawable/ic_volume_ringer_vibrate</item> + <item>com.android.systemui:drawable/ic_volume_voice</item> + <item>com.android.systemui:drawable/stat_sys_camera</item> + <item>com.android.systemui:drawable/stat_sys_managed_profile_status</item> + <item>com.android.systemui:drawable/stat_sys_mic_none</item> + <item>com.android.systemui:drawable/stat_sys_vpn_ic</item> + + </string-array> +</resources> diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml index 32dbc97a00fb..b95ec6be4c84 100644 --- a/packages/EasterEgg/res/values/strings.xml +++ b/packages/EasterEgg/res/values/strings.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,5 +14,11 @@ Copyright (C) 2018 The Android Open Source Project limitations under the License. --> <resources xmlns:android="http://schemas.android.com/apk/res/android"> - <string name="app_name" translatable="false">PAINT.APK</string> + <string name="app_name" translatable="false">Android Q Easter Egg</string> + + <!-- name of the Q easter egg, a nonogram-style icon puzzle --> + <string name="q_egg_name" translatable="false">Icon Quiz</string> + + <!-- name of the P easter egg, a humble paint program --> + <string name="p_egg_name" translatable="false">PAINT.APK</string> </resources> diff --git a/packages/EasterEgg/res/values/styles.xml b/packages/EasterEgg/res/values/styles.xml index 44e2ce52aab8..e576526f49b7 100644 --- a/packages/EasterEgg/res/values/styles.xml +++ b/packages/EasterEgg/res/values/styles.xml @@ -20,4 +20,16 @@ <item name="android:windowLightNavigationBar">true</item> </style> + <style name="QuaresTheme" parent="@android:style/Theme.DeviceDefault.DayNight"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowBackground">@android:color/transparent</item> + <item name="android:colorBackgroundCacheHint">@null</item> + <item name="android:windowShowWallpaper">true</item> + <item name="android:windowContentOverlay">@null</item> + <item name="android:windowNoTitle">true</item> + <item name="android:windowFullscreen">true</item> + <item name="android:statusBarColor">@android:color/transparent</item> + <item name="android:navigationBarColor">@android:color/transparent</item> + </style> + </resources> diff --git a/packages/EasterEgg/src/com/android/egg/quares/Quare.kt b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt new file mode 100644 index 000000000000..eb77362a0be2 --- /dev/null +++ b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt @@ -0,0 +1,168 @@ +/* + * Copyright 2019 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.egg.quares + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.drawable.Drawable +import android.graphics.drawable.Icon +import android.os.Parcel +import android.os.Parcelable +import java.util.ArrayList +import kotlin.math.abs +import kotlin.math.round + +class Quare(val width: Int, val height: Int, val depth: Int) : Parcelable { + private val data: IntArray = IntArray(width * height) + private val user: IntArray = data.copyOf() + + private fun loadAndQuantize(bitmap8bpp: Bitmap) { + bitmap8bpp.getPixels(data, 0, width, 0, 0, width, height) + if (depth == 8) return + val s = (255f / depth) + for (i in 0 until data.size) { + var f = (data[i] ushr 24).toFloat() / s + // f = f.pow(0.75f) // gamma adjust for bolder lines + f *= 1.25f // brightness adjust for bolder lines + f.coerceAtMost(1f) + data[i] = (round(f) * s).toInt() shl 24 + } + } + + fun isBlank(): Boolean { + return data.sum() == 0 + } + + fun load(drawable: Drawable) { + val resized = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8) + val canvas = Canvas(resized) + drawable.setBounds(0, 0, width, height) + drawable.setTint(0xFF000000.toInt()) + drawable.draw(canvas) + loadAndQuantize(resized) + resized.recycle() + } + + fun load(context: Context, icon: Icon) { + icon.loadDrawable(context)?.let { + load(it) + } + } + + fun bitmap(): Bitmap { + return Bitmap.createBitmap(data, width, height, Bitmap.Config.ALPHA_8) + } + + fun getUserMark(x: Int, y: Int): Int { + return user[y * width + x] ushr 24 + } + + fun setUserMark(x: Int, y: Int, v: Int) { + user[y * width + x] = v shl 24 + } + + fun getDataAt(x: Int, y: Int): Int { + return data[y * width + x] ushr 24 + } + + fun check(): Boolean { + return data.contentEquals(user) + } + + fun check(xSel: Int, ySel: Int): Boolean { + val xStart = if (xSel < 0) 0 else xSel + val xEnd = if (xSel < 0) width - 1 else xSel + val yStart = if (ySel < 0) 0 else ySel + val yEnd = if (ySel < 0) height - 1 else ySel + for (y in yStart..yEnd) + for (x in xStart..xEnd) + if (getDataAt(x, y) != getUserMark(x, y)) return false + return true + } + + fun errors(): IntArray { + return IntArray(width * height) { + abs(data[it] - user[it]) + } + } + + fun getRowClue(y: Int): IntArray { + return getClue(-1, y) + } + fun getColumnClue(x: Int): IntArray { + return getClue(x, -1) + } + fun getClue(xSel: Int, ySel: Int): IntArray { + val arr = ArrayList<Int>() + var len = 0 + val xStart = if (xSel < 0) 0 else xSel + val xEnd = if (xSel < 0) width - 1 else xSel + val yStart = if (ySel < 0) 0 else ySel + val yEnd = if (ySel < 0) height - 1 else ySel + for (y in yStart..yEnd) + for (x in xStart..xEnd) + if (getDataAt(x, y) != 0) { + len++ + } else if (len > 0) { + arr.add(len) + len = 0 + } + if (len > 0) arr.add(len) + else if (arr.size == 0) arr.add(0) + return arr.toIntArray() + } + + fun resetUserMarks() { + user.forEachIndexed { index, _ -> user[index] = 0 } + } + + // Parcelable interface + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(p: Parcel?, flags: Int) { + p?.let { + p.writeInt(width) + p.writeInt(height) + p.writeInt(depth) + p.writeIntArray(data) + p.writeIntArray(user) + } + } + + companion object CREATOR : Parcelable.Creator<Quare> { + override fun createFromParcel(p: Parcel?): Quare { + return p!!.let { + Quare( + p.readInt(), // width + p.readInt(), // height + p.readInt() // depth + ).also { + p.readIntArray(it.data) + p.readIntArray(it.user) + } + } + } + + override fun newArray(size: Int): Array<Quare?> { + return arrayOfNulls(size) + } + } +} diff --git a/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt new file mode 100644 index 000000000000..ce439a9a663c --- /dev/null +++ b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt @@ -0,0 +1,312 @@ +/* + * Copyright 2019 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.egg.quares + +import android.app.Activity +import android.content.Context +import android.content.res.Configuration +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Typeface +import android.graphics.drawable.Icon +import android.os.Bundle +import android.text.StaticLayout +import android.text.TextPaint +import android.util.Log +import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE +import android.widget.Button +import android.widget.CompoundButton +import android.widget.GridLayout + +import java.util.Random + +import com.android.egg.R + +const val TAG = "Quares" + +class QuaresActivity : Activity() { + private var q: Quare = Quare(16, 16, 1) + private var resId = 0 + private var resName = "" + private var icon: Icon? = null + + private lateinit var label: Button + private lateinit var grid: GridLayout + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + window.decorView.systemUiVisibility = + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE + + actionBar?.hide() + + setContentView(R.layout.activity_quares) + + grid = findViewById(R.id.grid) + label = findViewById(R.id.label) + + if (savedInstanceState != null) { + Log.v(TAG, "restoring puzzle from state") + q = savedInstanceState.getParcelable("q") ?: q + resId = savedInstanceState.getInt("resId") + resName = savedInstanceState.getString("resName", "") + loadPuzzle() + } + + label.setOnClickListener { newPuzzle() } + } + + override fun onResume() { + super.onResume() + if (resId == 0) { + // lazy init from onCreate + newPuzzle() + } + checkVictory() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + + outState.putParcelable("q", q) + outState.putInt("resId", resId) + outState.putString("resName", resName) + } + + fun newPuzzle() { + Log.v(TAG, "new puzzle...") + + q.resetUserMarks() + val oldResId = resId + resId = android.R.drawable.stat_sys_warning + try { + for (tries in 0..3) { + val ar = resources.obtainTypedArray(R.array.puzzles) + val newName = ar.getString(Random().nextInt(ar.length())) + if (newName == null) continue + + Log.v(TAG, "Looking for icon " + newName) + + val pkg = getPackageNameForResourceName(newName) + val newId = packageManager.getResourcesForApplication(pkg) + .getIdentifier(newName, "drawable", pkg) + if (newId == 0) { + Log.v(TAG, "oops, " + newName + " doesn't resolve from pkg " + pkg) + } else if (newId != oldResId) { + // got a good one + resId = newId + resName = newName + break + } + } + } catch (e: RuntimeException) { + Log.v(TAG, "problem loading puzzle, using fallback", e) + } + loadPuzzle() + } + + fun getPackageNameForResourceName(name: String): String { + return if (name.contains(":") && !name.startsWith("android:")) { + name.substring(0, name.indexOf(":")) + } else { + packageName + } + } + + fun checkVictory() { + if (q.check()) { + val dp = resources.displayMetrics.density + + val label: Button = findViewById(R.id.label) + label.text = resName.replace(Regex("^.*/"), "") + val drawable = icon?.loadDrawable(this)?.also { + it.setBounds(0, 0, (32 * dp).toInt(), (32 * dp).toInt()) + it.setTint(label.currentTextColor) + } + label.setCompoundDrawables(drawable, null, null, null) + + label.visibility = VISIBLE + } else { + label.visibility = GONE + } + } + + fun loadPuzzle() { + Log.v(TAG, "loading " + resName + " at " + q.width + "x" + q.height) + + val dp = resources.displayMetrics.density + + icon = Icon.createWithResource(getPackageNameForResourceName(resName), resId) + q.load(this, icon!!) + + if (q.isBlank()) { + // this is a really boring puzzle, let's try again + resId = 0 + resName = "" + recreate() + return + } + + grid.removeAllViews() + grid.columnCount = q.width + 1 + grid.rowCount = q.height + 1 + + label.visibility = GONE + + val orientation = resources.configuration.orientation + + // clean this up a bit + val minSide = resources.configuration.smallestScreenWidthDp - 25 // ish + val size = (minSide / (q.height + 0.5) * dp).toInt() + + val sb = StringBuffer() + + for (j in 0 until grid.rowCount) { + for (i in 0 until grid.columnCount) { + val tv: View + val params = GridLayout.LayoutParams().also { + it.width = size + it.height = size + it.setMargins(1, 1, 1, 1) + it.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, GridLayout.TOP) // UGH + } + val x = i - 1 + val y = j - 1 + if (i > 0 && j > 0) { + if (i == 1 && j > 1) sb.append("\n") + sb.append(if (q.getDataAt(x, y) == 0) " " else "X") + tv = PixelButton(this) + tv.isChecked = q.getUserMark(x, y) != 0 + tv.setOnClickListener { + q.setUserMark(x, y, if (tv.isChecked) 0xFF else 0) + val columnCorrect = (grid.getChildAt(i) as? ClueView)?.check(q) ?: false + val rowCorrect = (grid.getChildAt(j*(grid.columnCount)) as? ClueView) + ?.check(q) ?: false + if (columnCorrect && rowCorrect) { + checkVictory() + } else { + label.visibility = GONE + } + } + } else if (i == j) { // 0,0 + tv = View(this) + tv.visibility = GONE + } else { + tv = ClueView(this) + if (j == 0) { + tv.textRotation = 90f + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + params.height /= 2 + tv.showText = false + } else { + params.height = (96 * dp).toInt() + } + if (x >= 0) { + tv.setColumn(q, x) + } + } + if (i == 0) { + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + params.width /= 2 + tv.showText = false + } else { + params.width = (96 * dp).toInt() + } + if (y >= 0) { + tv.setRow(q, y) + } + } + } + grid.addView(tv, params) + } + } + + Log.v(TAG, "icon: \n" + sb) + } +} + +class PixelButton(context: Context) : CompoundButton(context) { + init { + setBackgroundResource(R.drawable.pixel_bg) + isClickable = true + isEnabled = true + } +} + +class ClueView(context: Context) : View(context) { + var row: Int = -1 + var column: Int = -1 + var textRotation: Float = 0f + var text: CharSequence = "" + var showText = true + val paint: TextPaint + val incorrectColor: Int + val correctColor: Int + + init { + setBackgroundColor(0) + paint = TextPaint().also { + it.textSize = 14f * context.resources.displayMetrics.density + it.color = context.getColor(R.color.q_clue_text) + it.typeface = Typeface.DEFAULT_BOLD + it.textAlign = Paint.Align.CENTER + } + incorrectColor = context.getColor(R.color.q_clue_bg) + correctColor = context.getColor(R.color.q_clue_bg_correct) + } + + fun setRow(q: Quare, row: Int): Boolean { + this.row = row + this.column = -1 + this.textRotation = 0f + text = q.getRowClue(row).joinToString("-") + return check(q) + } + fun setColumn(q: Quare, column: Int): Boolean { + this.column = column + this.row = -1 + this.textRotation = 90f + text = q.getColumnClue(column).joinToString("-") + return check(q) + } + fun check(q: Quare): Boolean { + val correct = q.check(column, row) + setBackgroundColor(if (correct) correctColor else incorrectColor) + return correct + } + + override fun onDraw(canvas: Canvas?) { + super.onDraw(canvas) + if (!showText) return + canvas?.let { + val x = canvas.width / 2f + val y = canvas.height / 2f + var textWidth = canvas.width + if (textRotation != 0f) { + canvas.rotate(textRotation, x, y) + textWidth = canvas.height + } + val textLayout = StaticLayout.Builder.obtain( + text, 0, text.length, paint, textWidth).build() + canvas.translate(x, y - textLayout.height / 2) + textLayout.draw(canvas) + } + } +} |