diff options
85 files changed, 744 insertions, 311 deletions
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk index 1ca14a6..397a7d1 100644 --- a/cmds/app_process/Android.mk +++ b/cmds/app_process/Android.mk @@ -2,15 +2,10 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -# TODO: Trying to link libsigchain as a static library prevents -# static linker from exporting necessary symbols. So as a workaround -# we use sigchain.o LOCAL_SRC_FILES:= \ - app_main.cpp \ - sigchain_proxy.cpp + app_main.cpp LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic -LOCAL_CPPFLAGS := -std=c++11 -Iart LOCAL_SHARED_LIBRARIES := \ libdl \ @@ -20,6 +15,8 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libandroid_runtime +LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain + LOCAL_MODULE:= app_process LOCAL_MULTILIB := both LOCAL_MODULE_STEM_32 := app_process32 @@ -36,10 +33,8 @@ ifeq ($(TARGET_ARCH),arm) include $(CLEAR_VARS) -# see comment above (~l5) LOCAL_SRC_FILES:= \ - app_main.cpp \ - sigchain_proxy.cpp + app_main.cpp LOCAL_SHARED_LIBRARIES := \ libcutils \ @@ -48,8 +43,10 @@ LOCAL_SHARED_LIBRARIES := \ libbinder \ libandroid_runtime +LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain + LOCAL_LDFLAGS := -ldl -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic -LOCAL_CPPFLAGS := -std=c++11 -Iart +LOCAL_CPPFLAGS := -std=c++11 LOCAL_MODULE := app_process__asan LOCAL_MODULE_TAGS := eng diff --git a/cmds/app_process/sigchain_proxy.cpp b/cmds/app_process/sigchain_proxy.cpp deleted file mode 100644 index bb7a678..0000000 --- a/cmds/app_process/sigchain_proxy.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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. - */ - -#include "sigchainlib/sigchain.cc" diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index a9deaf3..b8178b4 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -296,7 +296,7 @@ public final class Debug case 1: return "Stack"; case 2: return "Cursor"; case 3: return "Ashmem"; - case 4: return "Gfx driver"; + case 4: return "Gfx dev"; case 5: return "Other dev"; case 6: return ".so mmap"; case 7: return ".jar mmap"; @@ -306,9 +306,9 @@ public final class Debug case 11: return ".oat mmap"; case 12: return ".art mmap"; case 13: return "Other mmap"; - case 14: return "Graphics"; - case 15: return "GL"; - case 16: return "Memtrack"; + case 14: return "EGL mtrack"; + case 15: return "GL mtrack"; + case 16: return "Other mtrack"; case 17: return ".Heap"; case 18: return ".LOS"; case 19: return ".LinearAlloc"; diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index 820bf78..54c4505 100644 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -329,7 +329,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i String fullDateText = DateUtils.formatDateTime(mContext, millis, flags); mAnimator.announceForAccessibility(fullDateText); } - updatePickers(); } private void setCurrentView(final int viewIndex) { @@ -369,11 +368,14 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i @Override public void init(int year, int monthOfYear, int dayOfMonth, DatePicker.OnDateChangedListener callBack) { - mDateChangedListener = callBack; mCurrentDate.set(Calendar.YEAR, year); mCurrentDate.set(Calendar.MONTH, monthOfYear); mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); - updateDisplay(false); + + onDateChanged(false); + + // Set the listener last so that we don't call it. + mDateChangedListener = callBack; } @Override @@ -381,10 +383,29 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i mCurrentDate.set(Calendar.YEAR, year); mCurrentDate.set(Calendar.MONTH, month); mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + + onDateChanged(false); + } + + private void onDateChanged(boolean fromUser) { if (mDateChangedListener != null) { - mDateChangedListener.onDateChanged(mDelegator, year, month, dayOfMonth); + final int year = mCurrentDate.get(Calendar.YEAR); + final int monthOfYear = mCurrentDate.get(Calendar.MONTH); + final int dayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH); + mDateChangedListener.onDateChanged(mDelegator, year, monthOfYear, dayOfMonth); + } + + for (OnDateChangedListener listener : mListeners) { + listener.onDateChanged(); + } + + mDayPickerView.setDate(getSelectedDay().getTimeInMillis()); + + updateDisplay(fromUser); + + if (fromUser) { + tryVibrate(); } - updateDisplay(false); } @Override @@ -411,8 +432,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i } if (mCurrentDate.before(mTempDate)) { mCurrentDate.setTimeInMillis(minDate); - updatePickers(); - updateDisplay(false); + onDateChanged(false); } mMinDate.setTimeInMillis(minDate); mDayPickerView.setMinDate(minDate); @@ -433,8 +453,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i } if (mCurrentDate.after(mTempDate)) { mCurrentDate.setTimeInMillis(maxDate); - updatePickers(); - updateDisplay(false); + onDateChanged(false); } mMaxDate.setTimeInMillis(maxDate); mDayPickerView.setMaxDate(maxDate); @@ -573,9 +592,10 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i public void onYearSelected(int year) { adjustDayInMonthIfNeeded(mCurrentDate.get(Calendar.MONTH), year); mCurrentDate.set(Calendar.YEAR, year); - updatePickers(); + onDateChanged(true); + + // Auto-advance to month and day view. setCurrentView(MONTH_AND_DAY_VIEW); - updateDisplay(true); } // If the newly selected month / year does not contain the currently selected day number, @@ -612,14 +632,6 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i } } - private void updatePickers() { - for (OnDateChangedListener listener : mListeners) { - listener.onDateChanged(); - } - - mDayPickerView.setDate(getSelectedDay().getTimeInMillis()); - } - @Override public void registerOnDateChangedListener(OnDateChangedListener listener) { mListeners.add(listener); @@ -653,11 +665,7 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate i @Override public void onDaySelected(DayPickerView view, Calendar day) { mCurrentDate.setTimeInMillis(day.getTimeInMillis()); - - updatePickers(); - updateDisplay(true); - - tryVibrate(); + onDateChanged(true); } }; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 6769c85..ecc8d9d 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -425,6 +425,9 @@ <!-- Integer indicating minimum blacklisting delay of a wofo configuration due to connectin or auth errors --> <integer translatable="false" name="config_wifi_framework_network_black_list_min_time_milli">120000</integer> + <!-- Integer indicating RSSI boost given to current network --> + <integer translatable="false" name="config_wifi_framework_current_network_boost">25</integer> + <!-- Boolean indicating associated scan are allowed --> <bool translatable="false" name="config_wifi_framework_enable_associated_autojoin_scan">true</bool> diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml index bdb0324..e1e1ffe 100644 --- a/core/res/res/values/dimens_material.xml +++ b/core/res/res/values/dimens_material.xml @@ -56,6 +56,7 @@ <dimen name="action_bar_overflow_padding_start_material">6dp</dimen> <!-- Padding to add to the end of the overflow action button. --> <dimen name="action_bar_overflow_padding_end_material">10dp</dimen> + <dimen name="action_bar_elevation_material">4dp</dimen> <dimen name="action_button_min_width_overflow_material">36dp</dimen> <dimen name="action_button_min_width_material">48dp</dimen> @@ -87,9 +88,9 @@ <dimen name="floating_window_margin_bottom">32dp</dimen> <!-- Elevation when button is pressed --> - <dimen name="button_elevation_material">4dp</dimen> + <dimen name="button_elevation_material">2dp</dimen> <!-- Z translation to apply when button is pressed --> - <dimen name="button_pressed_z_material">2dp</dimen> + <dimen name="button_pressed_z_material">4dp</dimen> <!-- Default insets (outer padding) around buttons --> <dimen name="button_inset_vertical_material">6dp</dimen> <dimen name="button_inset_horizontal_material">@dimen/control_inset_material</dimen> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index d3d6d70..6220a1b 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -917,7 +917,7 @@ please see styles_device_defaults.xml. <item name="gravity">center_vertical</item> <item name="contentInsetStart">@dimen/action_bar_content_inset_material</item> <item name="contentInsetEnd">@dimen/action_bar_content_inset_material</item> - <item name="elevation">8dp</item> + <item name="elevation">@dimen/action_bar_elevation_material</item> <item name="popupTheme">?attr/actionBarPopupTheme</item> </style> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4f2ed22..d8c5f2c 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -338,6 +338,7 @@ <java-symbol type="integer" name="config_wifi_framework_max_connection_errors_to_blacklist" /> <java-symbol type="integer" name="config_wifi_framework_max_auth_errors_to_blacklist" /> <java-symbol type="integer" name="config_wifi_framework_network_black_list_min_time_milli" /> + <java-symbol type="integer" name="config_wifi_framework_current_network_boost" /> <java-symbol type="integer" name="config_bluetooth_max_advertisers" /> <java-symbol type="integer" name="config_bluetooth_max_scan_filters" /> <java-symbol type="integer" name="config_cursorWindowSize" /> diff --git a/docs/html/distribute/googleplay/wear.jd b/docs/html/distribute/googleplay/wear.jd index b6fc6b6..c0a0017 100644 --- a/docs/html/distribute/googleplay/wear.jd +++ b/docs/html/distribute/googleplay/wear.jd @@ -210,7 +210,7 @@ describe how to start building a great app experience for Wear. and the opt-in checkbox. </li> - <li>Click the checkbox next to <em>Distribute your app to Android Wear</em>. + <li>Click the checkbox next to <em>Distribute your app on Android Wear</em>. </li> <li>Click <strong>Save</strong> to save your Pricing and Distribution changes. diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js index 1b7cfc9..ab5a655 100644 --- a/docs/html/jd_collections.js +++ b/docs/html/jd_collections.js @@ -4,7 +4,7 @@ var RESOURCE_COLLECTIONS = { "resources": [ "training/building-wearables.html", "training/material/index.html", - "sdk/installing/studio.html" + "sdk/index.html" ] }, "index/primary/zhcn": { diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd index d1888fa..258fedb 100644 --- a/docs/html/tools/studio/index.jd +++ b/docs/html/tools/studio/index.jd @@ -114,8 +114,9 @@ specification and the files under {@code src/androidTest} directory for test cas <p> <img src="{@docRoot}images/tools/studio-project-layout.png" alt="" /></p> <p> <class="img-caption"><strong>Figure 3.</strong> Android Studio project structure</p> -<p>For more information, see <a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Project +Organization"class="external-link">IntelliJ project organization</a> and -<a href="{@docRoot}tools/workflow/project/index.html">Managing Projects</a>.</p> +<p>For more information, see +<a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Project+Organization"class="external-link">IntelliJ project organization</a> and +<a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.</p> <h3>Creating new files</h3> diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs index cb6a1de..9437c1b 100644 --- a/docs/html/tools/tools_toc.cs +++ b/docs/html/tools/tools_toc.cs @@ -122,7 +122,7 @@ <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/debugging/index.html"><span class="en">Debugging</span></a></div> <ul> - <li><a href="<?cs var:toroot ?>tools/debugging/debugging-projects.html"><span class="en">From Eclipse with ADT</span></a></li> + <li><a href="<?cs var:toroot ?>tools/debugging/debugging-studio.html"><span class="en">From Android Studio</span></a></li> <li><a href="<?cs var:toroot ?>tools/debugging/debugging-projects-cmdline.html"><span class="en">From Other IDEs</span></a></li> <li><a href="<?cs var:toroot ?>tools/debugging/ddms.html"><span class="en">Using DDMS</span></a></li> <li><a href="<?cs var:toroot ?>tools/debugging/debugging-log.html"><span class="en">Reading and Writing Logs</span></a></li> @@ -145,14 +145,6 @@ </ul> </li> - <li class="nav-section"> - <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/support-library/index.html"><span -class="en">Support Library</span></a></div> - <ul> - <li><a href="<?cs var:toroot ?>tools/support-library/features.html">Features</a></li> - <li><a href="<?cs var:toroot ?>tools/support-library/setup.html">Setup</a></li> - </ul> - </li> <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/help/index.html"><span diff --git a/docs/html/training/basics/actionbar/adding-buttons.jd b/docs/html/training/basics/actionbar/adding-buttons.jd index 26c9d0e..40d0bd1 100644 --- a/docs/html/training/basics/actionbar/adding-buttons.jd +++ b/docs/html/training/basics/actionbar/adding-buttons.jd @@ -1,4 +1,6 @@ page.title=Adding Action Buttons +page.tags=actionbar +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/basics/actionbar/index.jd b/docs/html/training/basics/actionbar/index.jd index 0303043..6a8eaff 100644 --- a/docs/html/training/basics/actionbar/index.jd +++ b/docs/html/training/basics/actionbar/index.jd @@ -1,5 +1,6 @@ page.title=Adding the Action Bar page.tags=actionbar +helpoutsWidget=true trainingnavtop=true startpage=true diff --git a/docs/html/training/basics/actionbar/overlaying.jd b/docs/html/training/basics/actionbar/overlaying.jd index 800cd44..634534e 100644 --- a/docs/html/training/basics/actionbar/overlaying.jd +++ b/docs/html/training/basics/actionbar/overlaying.jd @@ -1,4 +1,6 @@ page.title=Overlaying the Action Bar +page.tags=actionbar +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/basics/actionbar/setting-up.jd b/docs/html/training/basics/actionbar/setting-up.jd index 158ce92..bccbd04 100644 --- a/docs/html/training/basics/actionbar/setting-up.jd +++ b/docs/html/training/basics/actionbar/setting-up.jd @@ -1,4 +1,6 @@ page.title=Setting Up the Action Bar +page.tags=actionbar +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/basics/actionbar/styling.jd b/docs/html/training/basics/actionbar/styling.jd index 4128a97..7c63952 100644 --- a/docs/html/training/basics/actionbar/styling.jd +++ b/docs/html/training/basics/actionbar/styling.jd @@ -1,4 +1,6 @@ page.title=Styling the Action Bar +page.tags=actionbar +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/basics/data-storage/databases.jd b/docs/html/training/basics/data-storage/databases.jd index 6ea2140..4a91d0d 100644 --- a/docs/html/training/basics/data-storage/databases.jd +++ b/docs/html/training/basics/data-storage/databases.jd @@ -1,8 +1,8 @@ page.title=Saving Data in SQL Databases +page.tags=data storage +helpoutsWidget=true trainingnavtop=true -previous.title=Saving Data in Files -previous.link=files.html @jd:body diff --git a/docs/html/training/basics/data-storage/files.jd b/docs/html/training/basics/data-storage/files.jd index 52bea4c..49a9169 100644 --- a/docs/html/training/basics/data-storage/files.jd +++ b/docs/html/training/basics/data-storage/files.jd @@ -1,4 +1,6 @@ page.title=Saving Files +page.tags=data storage +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/basics/data-storage/index.jd b/docs/html/training/basics/data-storage/index.jd index fc0c8b5..aa223f6 100644 --- a/docs/html/training/basics/data-storage/index.jd +++ b/docs/html/training/basics/data-storage/index.jd @@ -1,5 +1,6 @@ page.title=Saving Data page.tags=data storage,files,sql,database,preferences +helpoutsWidget=true trainingnavtop=true startpage=true diff --git a/docs/html/training/basics/data-storage/shared-preferences.jd b/docs/html/training/basics/data-storage/shared-preferences.jd index a6717c4..debb17d 100644 --- a/docs/html/training/basics/data-storage/shared-preferences.jd +++ b/docs/html/training/basics/data-storage/shared-preferences.jd @@ -1,4 +1,6 @@ page.title=Saving Key-Value Sets +page.tags=data storage +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/notify-user/build-notification.jd b/docs/html/training/notify-user/build-notification.jd index 80f2cd5..d24a496 100644 --- a/docs/html/training/notify-user/build-notification.jd +++ b/docs/html/training/notify-user/build-notification.jd @@ -1,10 +1,8 @@ page.title=Building a Notification -parent.title=Notifying the User -parent.link=index.html +page.tags=notifications +helpoutsWidget=true trainingnavtop=true -next.title=Preserving Navigation when Starting an Activity -next.link=navigation.html @jd:body diff --git a/docs/html/training/notify-user/display-progress.jd b/docs/html/training/notify-user/display-progress.jd index c00576c..3439571 100644 --- a/docs/html/training/notify-user/display-progress.jd +++ b/docs/html/training/notify-user/display-progress.jd @@ -1,10 +1,8 @@ page.title=Displaying Progress in a Notification -parent.title=Notifying the User -parent.link=index.html +page.tags=notifications +helpoutsWidget=true trainingnavtop=true -previous.title=Using Expanded Notification Styles -previous.link=expanded.html @jd:body diff --git a/docs/html/training/notify-user/expanded.jd b/docs/html/training/notify-user/expanded.jd index a3cc6ad..b657426 100644 --- a/docs/html/training/notify-user/expanded.jd +++ b/docs/html/training/notify-user/expanded.jd @@ -1,10 +1,8 @@ page.title=Using Big View Styles -Styles parent.title=Notifying the User -parent.link=index.html +page.tags=notifications +helpoutsWidget=true trainingnavtop=true -next.title=Displaying Progress in a Notification -next.link=display-progress.html @jd:body diff --git a/docs/html/training/notify-user/index.jd b/docs/html/training/notify-user/index.jd index f7d0f87..616e767 100644 --- a/docs/html/training/notify-user/index.jd +++ b/docs/html/training/notify-user/index.jd @@ -1,5 +1,6 @@ page.title=Notifying the User page.tags=notifications +helpoutsWidget=true trainingnavtop=true startpage=true diff --git a/docs/html/training/notify-user/managing.jd b/docs/html/training/notify-user/managing.jd index 4782734..fc12cfb 100644 --- a/docs/html/training/notify-user/managing.jd +++ b/docs/html/training/notify-user/managing.jd @@ -1,10 +1,8 @@ page.title=Updating Notifications -parent.title=Notifying the User -parent.link=index.html +page.tags=notifications +helpoutsWidget=true trainingnavtop=true -next.title=Creating Expanded Notifications -next.link=expanded.html @jd:body diff --git a/docs/html/training/notify-user/navigation.jd b/docs/html/training/notify-user/navigation.jd index fc95013..b7051ab 100644 --- a/docs/html/training/notify-user/navigation.jd +++ b/docs/html/training/notify-user/navigation.jd @@ -1,10 +1,8 @@ page.title=Preserving Navigation when Starting an Activity -parent.title=Notifying the User -parent.link=index.html +page.tags=notifications +helpoutsWidget=true trainingnavtop=true -next.title=Updating Notifications -next.link=managing.html @jd:body diff --git a/docs/html/training/tv/discovery/in-app-search.jd b/docs/html/training/tv/discovery/in-app-search.jd index 28c7a35..fb7c097 100644 --- a/docs/html/training/tv/discovery/in-app-search.jd +++ b/docs/html/training/tv/discovery/in-app-search.jd @@ -1,5 +1,6 @@ page.title=Searching within TV Apps -page.tags="leanback" +page.tags=tv, leanback +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/tv/discovery/index.jd b/docs/html/training/tv/discovery/index.jd index 5849149..f22ca67 100644 --- a/docs/html/training/tv/discovery/index.jd +++ b/docs/html/training/tv/discovery/index.jd @@ -1,5 +1,6 @@ page.title=Helping Users Find Your Content on TV -page.tags="tv", "leanback" +page.tags=tv, leanback +helpoutsWidget=true startpage=true diff --git a/docs/html/training/tv/discovery/recommendations.jd b/docs/html/training/tv/discovery/recommendations.jd index a6eb152..0f6d256 100644 --- a/docs/html/training/tv/discovery/recommendations.jd +++ b/docs/html/training/tv/discovery/recommendations.jd @@ -1,5 +1,6 @@ page.title=Recommending TV Content -page.tags="recommendation","recommend" +page.tags=tv, recommendations +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/tv/games/index.jd b/docs/html/training/tv/games/index.jd index 5276d7f..371e9e9 100644 --- a/docs/html/training/tv/games/index.jd +++ b/docs/html/training/tv/games/index.jd @@ -1,5 +1,6 @@ page.title=Building TV Games -page.tags="tv", "games", "controller" +page.tags=tv, games, controller +helpoutsWidget=true page.image=images/games/game-controller-buttons_2x_crop.png page.metaDescription=How to bring your games to Android TV, including recommendations and examples. page.article=true diff --git a/docs/html/training/tv/playback/browse.jd b/docs/html/training/tv/playback/browse.jd index 9b25166..9c81597 100644 --- a/docs/html/training/tv/playback/browse.jd +++ b/docs/html/training/tv/playback/browse.jd @@ -1,5 +1,6 @@ page.title=Creating a Catalog Browser -page.tags="browsefragment","presenter","backgroundmanager" +page.tags=tv, browsefragment, presenter, backgroundmanager +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/tv/playback/details.jd b/docs/html/training/tv/playback/details.jd index 6391a49..bd6d67a 100644 --- a/docs/html/training/tv/playback/details.jd +++ b/docs/html/training/tv/playback/details.jd @@ -1,5 +1,6 @@ page.title=Building a Details View -page.tags="detailsfragment" +page.tags=tv, detailsfragment +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/tv/playback/index.jd b/docs/html/training/tv/playback/index.jd index 09c3f24..31c7524 100644 --- a/docs/html/training/tv/playback/index.jd +++ b/docs/html/training/tv/playback/index.jd @@ -1,5 +1,6 @@ page.title=Building TV Playback Apps -page.tags="tv","leanback" +page.tags=tv, leanback +helpoutsWidget=true startpage=true diff --git a/docs/html/training/tv/playback/now-playing.jd b/docs/html/training/tv/playback/now-playing.jd index b64beb0..e158697 100644 --- a/docs/html/training/tv/playback/now-playing.jd +++ b/docs/html/training/tv/playback/now-playing.jd @@ -1,5 +1,6 @@ page.title=Displaying a Now Playing Card -page.tags="nowplaying","mediasession" +page.tags=tv, mediasession +helpoutsWidget=true trainingnavtop=true diff --git a/docs/html/training/tv/start/hardware.jd b/docs/html/training/tv/start/hardware.jd index fc52602..b25a0dd 100644 --- a/docs/html/training/tv/start/hardware.jd +++ b/docs/html/training/tv/start/hardware.jd @@ -1,5 +1,6 @@ page.title=Handling TV Hardware -page.tags="unsupported" +page.tags=tv +helpoutsWidget=true trainingnavtop=true @jd:body diff --git a/docs/html/training/tv/start/index.jd b/docs/html/training/tv/start/index.jd index fb478a8..54ff2d9 100644 --- a/docs/html/training/tv/start/index.jd +++ b/docs/html/training/tv/start/index.jd @@ -1,5 +1,6 @@ page.title=Building TV Apps -page.tags="tv", "leanback" +page.tags=tv, leanback +helpoutsWidget=true startpage=true @jd:body diff --git a/docs/html/training/tv/start/layouts.jd b/docs/html/training/tv/start/layouts.jd index d2abe1d..a390702 100644 --- a/docs/html/training/tv/start/layouts.jd +++ b/docs/html/training/tv/start/layouts.jd @@ -1,4 +1,7 @@ page.title=Building Layouts for TV +page.tags=tv +helpoutsWidget=true + trainingnavtop=true @jd:body diff --git a/docs/html/training/tv/start/navigation.jd b/docs/html/training/tv/start/navigation.jd index 1c9faca..a94e3ae 100644 --- a/docs/html/training/tv/start/navigation.jd +++ b/docs/html/training/tv/start/navigation.jd @@ -1,5 +1,6 @@ page.title=Creating TV Navigation -page.tags="focus","selection","d-pad" +page.tags=tv, d-pad, focus +helpoutsWidget=true trainingnavtop=true @jd:body diff --git a/docs/html/training/tv/start/start.jd b/docs/html/training/tv/start/start.jd index aab1a39..e3b92c6 100644 --- a/docs/html/training/tv/start/start.jd +++ b/docs/html/training/tv/start/start.jd @@ -1,5 +1,6 @@ page.title=Get Started with TV Apps -page.tags="leanback","recyclerview","launcher" +page.tags=tv, leanback, recyclerview +helpoutsWidget=true trainingnavtop=true startpage=true diff --git a/docs/html/training/tv/tif/index.jd b/docs/html/training/tv/tif/index.jd index cde8ba7..9c10850 100644 --- a/docs/html/training/tv/tif/index.jd +++ b/docs/html/training/tv/tif/index.jd @@ -1,5 +1,6 @@ page.title=Building Live TV Apps -page.tags="tv", "tif" +page.tags=tv, tif +helpoutsWidget=true page.article=true @jd:body diff --git a/docs/html/training/wearables/apps/bt-debugging.jd b/docs/html/training/wearables/apps/bt-debugging.jd index 7569e7e..beded9e 100644 --- a/docs/html/training/wearables/apps/bt-debugging.jd +++ b/docs/html/training/wearables/apps/bt-debugging.jd @@ -1,4 +1,6 @@ page.title=Debugging over Bluetooth +page.tags=wear +helpoutsWidget=true @jd:body diff --git a/docs/html/training/wearables/apps/creating.jd b/docs/html/training/wearables/apps/creating.jd index 683dd31..c12ffa7 100644 --- a/docs/html/training/wearables/apps/creating.jd +++ b/docs/html/training/wearables/apps/creating.jd @@ -1,4 +1,6 @@ page.title=Creating and Running a Wearable App +page.tags=wear +helpoutsWidget=true @jd:body diff --git a/docs/html/training/wearables/apps/index.jd b/docs/html/training/wearables/apps/index.jd index 4bdd6bf..812f893 100644 --- a/docs/html/training/wearables/apps/index.jd +++ b/docs/html/training/wearables/apps/index.jd @@ -1,5 +1,6 @@ page.title=Creating Wearable Apps -page.tags="wear","wearable","app" +page.tags=wear +helpoutsWidget=true page.image=wear/images/01_create.png @jd:body diff --git a/docs/html/training/wearables/apps/layouts.jd b/docs/html/training/wearables/apps/layouts.jd index 4eeb281..69e57ca 100644 --- a/docs/html/training/wearables/apps/layouts.jd +++ b/docs/html/training/wearables/apps/layouts.jd @@ -1,4 +1,6 @@ page.title=Creating Custom Layouts +page.tags=wear +helpoutsWidget=true @jd:body diff --git a/docs/html/training/wearables/apps/packaging.jd b/docs/html/training/wearables/apps/packaging.jd index 180f730..9c42978 100644 --- a/docs/html/training/wearables/apps/packaging.jd +++ b/docs/html/training/wearables/apps/packaging.jd @@ -1,4 +1,6 @@ page.title=Packaging Wearable Apps +page.tags=wear +helpoutsWidget=true @jd:body diff --git a/docs/html/training/wearables/apps/voice.jd b/docs/html/training/wearables/apps/voice.jd index 4aa8031..6d49319 100644 --- a/docs/html/training/wearables/apps/voice.jd +++ b/docs/html/training/wearables/apps/voice.jd @@ -1,4 +1,7 @@ page.title=Adding Voice Capabilities +page.tags=wear +helpoutsWidget=true + @jd:body <div id="tb-wrapper"> diff --git a/docs/html/training/wearables/notifications/creating.jd b/docs/html/training/wearables/notifications/creating.jd index 57ac36e..542664b 100644 --- a/docs/html/training/wearables/notifications/creating.jd +++ b/docs/html/training/wearables/notifications/creating.jd @@ -1,4 +1,6 @@ -page.title=Creating a Notification +page.title=Creating a Notification for Wearables +page.tags=notifications +helpoutsWidget=true @jd:body diff --git a/docs/html/training/wearables/notifications/index.jd b/docs/html/training/wearables/notifications/index.jd index 2833dfa..6be945c 100644 --- a/docs/html/training/wearables/notifications/index.jd +++ b/docs/html/training/wearables/notifications/index.jd @@ -1,6 +1,8 @@ page.title=Adding Wearable Features to Notifications -page.tags="wear","notifications","wearables" +page.tags=notifications, wear page.image=wear/images/01_notifications.png +helpoutsWidget=true + @jd:body <div id="tb-wrapper"> diff --git a/docs/html/training/wearables/notifications/pages.jd b/docs/html/training/wearables/notifications/pages.jd index 6315037..41a3d7e 100644 --- a/docs/html/training/wearables/notifications/pages.jd +++ b/docs/html/training/wearables/notifications/pages.jd @@ -1,4 +1,6 @@ page.title=Adding Pages to a Notification +page.tags=notifications +helpoutsWidget=true @jd:body diff --git a/docs/html/training/wearables/notifications/stacks.jd b/docs/html/training/wearables/notifications/stacks.jd index 9e70e1b..8056fc8 100644 --- a/docs/html/training/wearables/notifications/stacks.jd +++ b/docs/html/training/wearables/notifications/stacks.jd @@ -1,4 +1,6 @@ page.title=Stacking Notifications +page.tags=notifications +helpoutsWidget=true @jd:body diff --git a/docs/html/training/wearables/notifications/voice-input.jd b/docs/html/training/wearables/notifications/voice-input.jd index 5a49343..73936f9 100644 --- a/docs/html/training/wearables/notifications/voice-input.jd +++ b/docs/html/training/wearables/notifications/voice-input.jd @@ -1,4 +1,6 @@ page.title=Receiving Voice Input in a Notification +page.tags=notifications +helpoutsWidget=true @jd:body diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 1e360d3..3fe408a 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -714,10 +714,17 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { mDrawableFutures = new SparseArray<ConstantStateFuture>(mNumChildren); } + // Create futures for drawables with constant states. If a + // drawable doesn't have a constant state, then we can't clone + // it and we'll have to reference the original. final int N = mNumChildren; for (int i = 0; i < N; i++) { if (origDr[i] != null) { - mDrawableFutures.put(i, new ConstantStateFuture(origDr[i])); + if (origDr[i].getConstantState() != null) { + mDrawableFutures.put(i, new ConstantStateFuture(origDr[i])); + } else { + mDrawables[i] = origDr[i]; + } } } } else { diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 94c7026..cb42397 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -1795,5 +1795,7 @@ public class GradientDrawable extends Drawable { mStrokePaint.setPathEffect(e); } } + + mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); } } diff --git a/include/androidfw/AttributeFinder.h b/include/androidfw/AttributeFinder.h index a0ffeb3..acf7056 100644 --- a/include/androidfw/AttributeFinder.h +++ b/include/androidfw/AttributeFinder.h @@ -64,6 +64,7 @@ private: void jumpToClosestAttribute(uint32_t packageId); void markCurrentPackageId(uint32_t packageId); + bool mFirstTime; Iterator mBegin; Iterator mEnd; Iterator mCurrent; @@ -81,7 +82,8 @@ private: template <typename Derived, typename Iterator> inline BackTrackingAttributeFinder<Derived, Iterator>::BackTrackingAttributeFinder(const Iterator& begin, const Iterator& end) - : mBegin(begin) + : mFirstTime(true) + , mBegin(begin) , mEnd(end) , mCurrent(begin) , mLargest(begin) @@ -145,8 +147,11 @@ Iterator BackTrackingAttributeFinder<Derived, Iterator>::find(uint32_t attr) { return mEnd; } - if (mCurrentAttr == 0) { - // One-time initialization. + if (mFirstTime) { + // One-time initialization. We do this here instead of the constructor + // because the derived class we access in getAttribute() may not be + // fully constructed. + mFirstTime = false; mCurrentAttr = static_cast<const Derived*>(this)->getAttribute(mBegin); mLastPackageId = getPackage(mCurrentAttr); markCurrentPackageId(mLastPackageId); diff --git a/libs/androidfw/tests/AttributeFinder_test.cpp b/libs/androidfw/tests/AttributeFinder_test.cpp index 664709c..5054624 100644 --- a/libs/androidfw/tests/AttributeFinder_test.cpp +++ b/libs/androidfw/tests/AttributeFinder_test.cpp @@ -50,6 +50,10 @@ static const uint32_t packageUnsortedAttributes[] = { 0x01010002, 0x01010004, 0x7f010001 }; +static const uint32_t singlePackageAttributes[] = { + 0x7f010007, 0x7f01000a, 0x7f01000d, 0x00000000 +}; + TEST(AttributeFinderTest, IteratesSequentially) { const int end = sizeof(sortedAttributes) / sizeof(*sortedAttributes); MockAttributeFinder finder(sortedAttributes, end); @@ -109,3 +113,16 @@ TEST(AttributeFinderTest, FindAttributesInPackageUnsortedAttributeList) { EXPECT_EQ(1, finder.find(0x02010010)); EXPECT_EQ(6, finder.find(0x7f010001)); } + +TEST(AttributeFinderTest, FindAttributesInSinglePackageAttributeList) { + const int end = sizeof(singlePackageAttributes) / sizeof(*singlePackageAttributes); + MockAttributeFinder finder(singlePackageAttributes, end); + + EXPECT_EQ(end, finder.find(0x010100f4)); + EXPECT_EQ(end, finder.find(0x010100f5)); + EXPECT_EQ(end, finder.find(0x010100f6)); + EXPECT_EQ(end, finder.find(0x010100f7)); + EXPECT_EQ(end, finder.find(0x010100f8)); + EXPECT_EQ(end, finder.find(0x010100fa)); + EXPECT_EQ(0, finder.find(0x7f010007)); +} diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp index 21c869b..b2dba00 100644 --- a/libs/hwui/AmbientShadow.cpp +++ b/libs/hwui/AmbientShadow.cpp @@ -325,6 +325,7 @@ void AmbientShadow::createAmbientShadow(bool isCasterOpaque, // At the end, update the real index and vertex buffer size. shadowVertexBuffer.updateVertexCount(vertexBufferIndex); shadowVertexBuffer.updateIndexCount(indexBufferIndex); + shadowVertexBuffer.computeBounds<AlphaVertex>(); ShadowTessellator::checkOverflow(vertexBufferIndex, totalVertexCount, "Ambient Vertex Buffer"); ShadowTessellator::checkOverflow(indexBufferIndex, totalIndexCount, "Ambient Index Buffer"); diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index e5a93bd..c6de535 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -36,39 +36,37 @@ void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) { ATRACE_NAME("AssetAtlas::init"); mImage = new Image(buffer); - if (mImage->getTexture()) { - Caches& caches = Caches::getInstance(); - - mTexture = new Texture(caches); - mTexture->id = mImage->getTexture(); - mTexture->width = buffer->getWidth(); - mTexture->height = buffer->getHeight(); - - createEntries(caches, map, count); + if (!mTexture) { + Caches& caches = Caches::getInstance(); + mTexture = new Texture(caches); + mTexture->width = buffer->getWidth(); + mTexture->height = buffer->getHeight(); + createEntries(caches, map, count); + } } else { ALOGW("Could not create atlas image"); - delete mImage; mImage = NULL; - mTexture = NULL; } - mGenerationId++; + updateTextureId(); } void AssetAtlas::terminate() { if (mImage) { delete mImage; mImage = NULL; + updateTextureId(); + } +} - delete mTexture; - mTexture = NULL; - for (size_t i = 0; i < mEntries.size(); i++) { - delete mEntries.valueAt(i); - } - mEntries.clear(); +void AssetAtlas::updateTextureId() { + mTexture->id = mImage ? mImage->getTexture() : 0; + for (size_t i = 0; i < mEntries.size(); i++) { + AssetAtlas::Entry* entry = mEntries.valueAt(i); + entry->texture->id = mTexture->id; } } @@ -133,7 +131,6 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { y / height, (y + bitmap->height()) / height); Texture* texture = new DelegateTexture(caches, mTexture); - texture->id = mTexture->id; texture->blend = !bitmap->isOpaque(); texture->width = bitmap->width(); texture->height = bitmap->height(); diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index 2ec556e..fffd740 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -106,7 +106,7 @@ public: friend class AssetAtlas; }; - AssetAtlas(): mTexture(NULL), mImage(NULL), mGenerationId(0), + AssetAtlas(): mTexture(NULL), mImage(NULL), mBlendKey(true), mOpaqueKey(false) { } ~AssetAtlas() { terminate(); } @@ -130,7 +130,7 @@ public: * After calling this method, the width, height * and texture are set to 0. */ - ANDROID_API void terminate(); + void terminate(); /** * Returns the width of this atlas in pixels. @@ -168,21 +168,13 @@ public: */ Texture* getEntryTexture(const SkBitmap* bitmap) const; - /** - * Returns the current generation id of the atlas. - */ - uint32_t getGenerationId() const { - return mGenerationId; - } - private: void createEntries(Caches& caches, int64_t* map, int count); + void updateTextureId(); Texture* mTexture; Image* mImage; - uint32_t mGenerationId; - const bool mBlendKey; const bool mOpaqueKey; diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 6453206..4bbe6ed 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -237,8 +237,6 @@ void Caches::terminate() { programCache.clear(); currentProgram = NULL; - assetAtlas.terminate(); - patchCache.clear(); clearGarbage(); diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index e338686..2e179af 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -348,8 +348,6 @@ public: Dither dither; Stencil stencil; - AssetAtlas assetAtlas; - bool gpuPixelBuffersEnabled; // Debug methods diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index cb8a8d1..7a43a2a 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -77,18 +77,14 @@ public: OpenGLRenderer& mRenderer; const int mReplayFlags; - // Allocator with the lifetime of a single frame. - // replay uses an Allocator owned by the struct, while defer shares the DeferredDisplayList's Allocator + // Allocator with the lifetime of a single frame. replay uses an Allocator owned by the struct, + // while defer shares the DeferredDisplayList's Allocator + // TODO: move this allocator to be owned by object with clear frame lifecycle LinearAllocator * const mAllocator; SkPath* allocPathForFrame() { - mTempPaths.push_back(); - return &mTempPaths.back(); + return mRenderer.allocPathForFrame(); } - -private: - // Paths kept alive for the duration of the frame - std::vector<SkPath> mTempPaths; }; class DeferStateStruct : public PlaybackStateStruct { diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 96e76d0..8a5e21d 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -32,6 +32,7 @@ #include "AssetAtlas.h" #include "DeferredDisplayList.h" #include "DisplayListRenderer.h" +#include "RenderState.h" #include "UvMapper.h" #include "utils/LinearAllocator.h" @@ -647,24 +648,17 @@ public: DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint) : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint) , mBitmap(bitmap) - , mAtlas(Caches::getInstance().assetAtlas) { - mEntry = mAtlas.getEntry(bitmap); - if (mEntry) { - mEntryGenerationId = mAtlas.getGenerationId(); - mUvMapper = mEntry->uvMapper; - } + , mEntryValid(false), mEntry(NULL) { } virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { return renderer.drawBitmap(mBitmap, getPaint(renderer)); } - AssetAtlas::Entry* getAtlasEntry() { - // The atlas entry is stale, let's get a new one - if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) { - mEntryGenerationId = mAtlas.getGenerationId(); - mEntry = mAtlas.getEntry(mBitmap); - mUvMapper = mEntry->uvMapper; + AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) { + if (!mEntryValid) { + mEntryValid = true; + mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap); } return mEntry; } @@ -700,7 +694,7 @@ public: pureTranslate &= state.mMatrix.isPureTranslate(); Rect texCoords(0, 0, 1, 1); - ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords); + ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords); SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top); SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); @@ -729,7 +723,7 @@ public: virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, const DeferredDisplayState& state) { deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; - deferInfo.mergeId = getAtlasEntry() ? + deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap; // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation @@ -742,13 +736,17 @@ public: (mBitmap->colorType() != kAlpha_8_SkColorType); } + void uvMap(OpenGLRenderer& renderer, Rect& texCoords) { + if (getAtlasEntry(renderer)) { + mEntry->uvMapper.map(texCoords); + } + } + const SkBitmap* bitmap() { return mBitmap; } protected: const SkBitmap* mBitmap; - const AssetAtlas& mAtlas; - uint32_t mEntryGenerationId; + bool mEntryValid; AssetAtlas::Entry* mEntry; - UvMapper mUvMapper; }; class DrawBitmapRectOp : public DrawBoundedOp { @@ -841,18 +839,13 @@ public: float left, float top, float right, float bottom, const SkPaint* paint) : DrawBoundedOp(left, top, right, bottom, paint), mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL), - mAtlas(Caches::getInstance().assetAtlas) { - mEntry = mAtlas.getEntry(bitmap); - if (mEntry) { - mEntryGenerationId = mAtlas.getGenerationId(); - } + mEntryValid(false), mEntry(NULL) { }; - AssetAtlas::Entry* getAtlasEntry() { - // The atlas entry is stale, let's get a new one - if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) { - mEntryGenerationId = mAtlas.getGenerationId(); - mEntry = mAtlas.getEntry(mBitmap); + AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) { + if (!mEntryValid) { + mEntryValid = true; + mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap); } return mEntry; } @@ -860,7 +853,7 @@ public: const Patch* getMesh(OpenGLRenderer& renderer) { if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) { PatchCache& cache = renderer.getCaches().patchCache; - mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(), + mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(), mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch); mGenerationId = cache.getGenerationId(); } @@ -942,14 +935,14 @@ public: indexCount += opMesh->indexCount; } - return renderer.drawPatches(mBitmap, getAtlasEntry(), + return renderer.drawPatches(mBitmap, getAtlasEntry(renderer), &vertices[0], indexCount, getPaint(renderer)); } virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { // We're not calling the public variant of drawPatch() here // This method won't perform the quickReject() since we've already done it at this point - return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(), + return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer), mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); } @@ -964,7 +957,7 @@ public: virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, const DeferredDisplayState& state) { deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch; - deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap; + deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap; deferInfo.mergeable = state.mMatrix.isPureTranslate() && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque(); @@ -977,8 +970,7 @@ private: uint32_t mGenerationId; const Patch* mMesh; - const AssetAtlas& mAtlas; - uint32_t mEntryGenerationId; + bool mEntryValid; AssetAtlas::Entry* mEntry; }; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 075f2c5..7285496 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -311,6 +311,11 @@ void OpenGLRenderer::finish() { renderOverdraw(); endTiling(); + for (size_t i = 0; i < mTempPaths.size(); i++) { + delete mTempPaths[i]; + } + mTempPaths.clear(); + // When finish() is invoked on FBO 0 we've reached the end // of the current frame if (getTargetFbo() == 0) { @@ -2049,7 +2054,7 @@ status_t OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, i } mCaches.activeTexture(0); - Texture* texture = mCaches.assetAtlas.getEntryTexture(bitmap); + Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap); const UvMapper& mapper(getMapper(texture)); for (int32_t y = 0; y < meshHeight; y++) { @@ -2232,7 +2237,7 @@ status_t OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* return DrawGlInfo::kStatusDone; } - AssetAtlas::Entry* entry = mCaches.assetAtlas.getEntry(bitmap); + AssetAtlas::Entry* entry = mRenderState.assetAtlas().getEntry(bitmap); const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(), right - left, bottom - top, patch); @@ -3028,7 +3033,7 @@ const SkPaint* OpenGLRenderer::filterPaint(const SkPaint* paint) { /////////////////////////////////////////////////////////////////////////////// Texture* OpenGLRenderer::getTexture(const SkBitmap* bitmap) { - Texture* texture = mCaches.assetAtlas.getEntryTexture(bitmap); + Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap); if (!texture) { return mCaches.textureCache.get(bitmap); } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index e1c3d10..5eee2e2 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -342,6 +342,12 @@ public: uint8_t getAmbientShadowAlpha() const { return mAmbientShadowAlpha; } uint8_t getSpotShadowAlpha() const { return mSpotShadowAlpha; } + SkPath* allocPathForFrame() { + SkPath* path = new SkPath(); + mTempPaths.push_back(path); + return path; + } + protected: /** * Perform the setup specific to a frame. This method does not @@ -1014,6 +1020,9 @@ private: uint8_t mAmbientShadowAlpha; uint8_t mSpotShadowAlpha; + // Paths kept alive for the duration of the frame + std::vector<SkPath*> mTempPaths; + friend class Layer; friend class TextSetupFunctor; friend class DrawBitmapOp; diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp index a8cf26f..d1f5f4e 100644 --- a/libs/hwui/RenderState.cpp +++ b/libs/hwui/RenderState.cpp @@ -38,6 +38,7 @@ void RenderState::onGLContextCreated() { mCaches = &Caches::getInstance(); mCaches->init(); mCaches->setRenderState(this); + mCaches->textureCache.setAssetAtlas(&mAssetAtlas); } void RenderState::onGLContextDestroyed() { @@ -72,6 +73,7 @@ void RenderState::onGLContextDestroyed() { LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size); } */ + mAssetAtlas.terminate(); } void RenderState::setViewport(GLsizei width, GLsizei height) { diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h index afeef95..1ecfb1c 100644 --- a/libs/hwui/RenderState.h +++ b/libs/hwui/RenderState.h @@ -23,6 +23,7 @@ #include <private/hwui/DrawGlInfo.h> +#include "AssetAtlas.h" #include "Caches.h" #include "utils/Macros.h" @@ -73,6 +74,8 @@ public: // more thinking... void postDecStrong(VirtualLightRefBase* object); + AssetAtlas& assetAtlas() { return mAssetAtlas; } + private: friend class renderthread::RenderThread; friend class Caches; @@ -86,6 +89,7 @@ private: renderthread::RenderThread& mRenderThread; Caches* mCaches; + AssetAtlas mAssetAtlas; std::set<const Layer*> mActiveLayers; std::set<renderthread::CanvasContext*> mRegisteredContexts; diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 5bad2fc..63454d8 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -24,6 +24,7 @@ #include <utils/Mutex.h> +#include "AssetAtlas.h" #include "Caches.h" #include "TextureCache.h" #include "Properties.h" @@ -39,7 +40,7 @@ namespace uirenderer { TextureCache::TextureCache(): mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity), mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)), - mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) { + mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE), mAssetAtlas(0) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) { INIT_LOGD(" Setting texture cache size to %sMB", property); @@ -62,7 +63,7 @@ TextureCache::TextureCache(): TextureCache::TextureCache(uint32_t maxByteSize): mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity), - mSize(0), mMaxSize(maxByteSize) { + mSize(0), mMaxSize(maxByteSize), mAssetAtlas(0) { init(); } @@ -124,6 +125,10 @@ void TextureCache::operator()(uint32_t&, Texture*& texture) { // Caching /////////////////////////////////////////////////////////////////////////////// +void TextureCache::setAssetAtlas(AssetAtlas* assetAtlas) { + mAssetAtlas = assetAtlas; +} + void TextureCache::resetMarkInUse() { LruCache<uint32_t, Texture*>::Iterator iter(mCache); while (iter.next()) { @@ -143,6 +148,13 @@ bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) { // Returns a prepared Texture* that either is already in the cache or can fit // in the cache (and is thus added to the cache) Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) { + if (CC_LIKELY(mAssetAtlas)) { + AssetAtlas::Entry* entry = mAssetAtlas->getEntry(bitmap); + if (CC_UNLIKELY(entry)) { + return entry->texture; + } + } + Texture* texture = mCache.get(bitmap->pixelRef()->getStableID()); if (!texture) { diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 3e94d1f..cf8d134 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -44,6 +44,8 @@ namespace uirenderer { // Classes /////////////////////////////////////////////////////////////////////////////// +class AssetAtlas; + /** * A simple LRU texture cache. The cache has a maximum size expressed in bytes. * Any texture added to the cache causing the cache to grow beyond the maximum @@ -123,6 +125,8 @@ public: */ void setFlushRate(float flushRate); + void setAssetAtlas(AssetAtlas* assetAtlas); + private: bool canMakeTextureFromBitmap(const SkBitmap* bitmap); @@ -155,6 +159,8 @@ private: Vector<uint32_t> mGarbage; mutable Mutex mLock; + + AssetAtlas* mAssetAtlas; }; // class TextureCache }; // namespace uirenderer diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index 378cf61..8fb1b10 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -175,7 +175,8 @@ void EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer, void EglManager::initAtlas() { if (mAtlasBuffer.get()) { - Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize); + mRenderThread.renderState().assetAtlas().init(mAtlasBuffer, + mAtlasMap, mAtlasMapSize); } } diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 0e69f74..b606a6f 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -197,6 +197,7 @@ <!-- Alternate Recents --> <activity android:name=".recents.RecentsActivity" android:label="@string/accessibility_desc_recent_apps" + android:exported="false" android:launchMode="singleInstance" android:excludeFromRecents="true" android:stateNotNeeded="true" @@ -207,6 +208,17 @@ </intent-filter> </activity> + <receiver android:name=".recents.RecentsUserEventProxyReceiver" + android:exported="false"> + <intent-filter> + <action android:name="com.android.systemui.recents.action.SHOW_RECENTS_FOR_USER" /> + <action android:name="com.android.systemui.recents.action.HIDE_RECENTS_FOR_USER" /> + <action android:name="com.android.systemui.recents.action.TOGGLE_RECENTS_FOR_USER" /> + <action android:name="com.android.systemui.recents.action.PRELOAD_RECENTS_FOR_USER" /> + <action android:name="com.android.systemui.recents.action.CONFIG_CHANGED_FOR_USER" /> + </intent-filter> + </receiver> + <!-- started from UsbDeviceSettingsManager --> <activity android:name=".usb.UsbConfirmActivity" android:exported="true" diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java index 9a55590..e9f3cf9 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java @@ -18,6 +18,7 @@ package com.android.systemui.recent; import android.app.ActivityOptions; import android.content.ActivityNotFoundException; +import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; @@ -44,16 +45,29 @@ public class Recents extends SystemUI implements RecentsComponent { // Which recents to use boolean mUseAlternateRecents = true; - AlternateRecentsComponent mAlternateRecents; boolean mBootCompleted = false; + static AlternateRecentsComponent sAlternateRecents; + + /** Returns the Recents component, creating a new one in-process if necessary. */ + public static AlternateRecentsComponent getRecentsComponent(Context context, + boolean forceInitialize) { + if (sAlternateRecents == null) { + sAlternateRecents = new AlternateRecentsComponent(context); + if (forceInitialize) { + sAlternateRecents.onStart(); + sAlternateRecents.onBootCompleted(); + } + } + return sAlternateRecents; + } @Override public void start() { if (mUseAlternateRecents) { - if (mAlternateRecents == null) { - mAlternateRecents = new AlternateRecentsComponent(mContext); + if (sAlternateRecents == null) { + sAlternateRecents = getRecentsComponent(mContext, false); } - mAlternateRecents.onStart(); + sAlternateRecents.onStart(); } putComponent(RecentsComponent.class, this); @@ -62,8 +76,8 @@ public class Recents extends SystemUI implements RecentsComponent { @Override protected void onBootCompleted() { if (mUseAlternateRecents) { - if (mAlternateRecents != null) { - mAlternateRecents.onBootCompleted(); + if (sAlternateRecents != null) { + sAlternateRecents.onBootCompleted(); } } mBootCompleted = true; @@ -72,14 +86,14 @@ public class Recents extends SystemUI implements RecentsComponent { @Override public void showRecents(boolean triggeredFromAltTab, View statusBarView) { if (mUseAlternateRecents) { - mAlternateRecents.onShowRecents(triggeredFromAltTab, statusBarView); + sAlternateRecents.onShowRecents(triggeredFromAltTab); } } @Override public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { if (mUseAlternateRecents) { - mAlternateRecents.onHideRecents(triggeredFromAltTab, triggeredFromHomeKey); + sAlternateRecents.onHideRecents(triggeredFromAltTab, triggeredFromHomeKey); } else { Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT); intent.setPackage("com.android.systemui"); @@ -93,7 +107,7 @@ public class Recents extends SystemUI implements RecentsComponent { public void toggleRecents(Display display, int layoutDirection, View statusBarView) { if (mUseAlternateRecents) { // Launch the alternate recents if required - mAlternateRecents.onToggleRecents(statusBarView); + sAlternateRecents.onToggleRecents(); return; } @@ -241,14 +255,14 @@ public class Recents extends SystemUI implements RecentsComponent { @Override protected void onConfigurationChanged(Configuration newConfig) { if (mUseAlternateRecents) { - mAlternateRecents.onConfigurationChanged(newConfig); + sAlternateRecents.onConfigurationChanged(newConfig); } } @Override public void preloadRecents() { if (mUseAlternateRecents) { - mAlternateRecents.onPreloadRecents(); + sAlternateRecents.onPreloadRecents(); } else { Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT); intent.setClassName("com.android.systemui", @@ -262,7 +276,7 @@ public class Recents extends SystemUI implements RecentsComponent { @Override public void cancelPreloadingRecents() { if (mUseAlternateRecents) { - mAlternateRecents.onCancelPreloadingRecents(); + sAlternateRecents.onCancelPreloadingRecents(); } else { Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT); intent.setClassName("com.android.systemui", @@ -276,21 +290,21 @@ public class Recents extends SystemUI implements RecentsComponent { @Override public void showNextAffiliatedTask() { if (mUseAlternateRecents) { - mAlternateRecents.onShowNextAffiliatedTask(); + sAlternateRecents.onShowNextAffiliatedTask(); } } @Override public void showPrevAffiliatedTask() { if (mUseAlternateRecents) { - mAlternateRecents.onShowPrevAffiliatedTask(); + sAlternateRecents.onShowPrevAffiliatedTask(); } } @Override public void setCallback(Callbacks cb) { if (mUseAlternateRecents) { - mAlternateRecents.setRecentsComponentCallback(cb); + sAlternateRecents.setRecentsComponentCallback(cb); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index f1bf66d..09a6ccc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -27,6 +27,7 @@ import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; @@ -38,7 +39,6 @@ import android.os.UserHandle; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; - import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.recents.misc.Console; @@ -57,12 +57,27 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +/** + * Annotation for a method that is only called from the primary user's SystemUI process and will be + * proxied to the current user. + */ +@interface ProxyFromPrimaryToCurrentUser {} +/** + * Annotation for a method that may be called from any user's SystemUI process and will be proxied + * to the primary user. + */ +@interface ProxyFromAnyToPrimaryUser {} /** A proxy implementation for the recents component */ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener { - final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab"; - final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey"; + final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "triggeredFromAltTab"; + final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "triggeredFromHomeKey"; + final public static String EXTRA_RECENTS_VISIBILITY = "recentsVisibility"; + + // Owner proxy events + final public static String ACTION_PROXY_NOTIFY_RECENTS_VISIBLITY_TO_OWNER = + "action_notify_recents_visibility_change"; final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation"; final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity"; @@ -78,9 +93,22 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta * An implementation of ITaskStackListener, that allows us to listen for changes to the system * task stacks and update recents accordingly. */ - class TaskStackListenerImpl extends ITaskStackListener.Stub { + class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable { + Handler mHandler; + + public TaskStackListenerImpl(Handler handler) { + mHandler = handler; + } + @Override public void onTaskStackChanged() { + // Debounce any task stack changes + mHandler.removeCallbacks(this); + mHandler.post(this); + } + + /** Preloads the next task */ + public void run() { RecentsConfiguration config = RecentsConfiguration.getInstance(); if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { // Load the next task only if we aren't svelte @@ -96,6 +124,20 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } } + /** + * A proxy for Recents events which happens strictly for the owner. + */ + class RecentsOwnerEventProxyReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + switch (intent.getAction()) { + case ACTION_PROXY_NOTIFY_RECENTS_VISIBLITY_TO_OWNER: + visibilityChanged(intent.getBooleanExtra(EXTRA_RECENTS_VISIBILITY, false)); + break; + } + } + } + static RecentsComponent.Callbacks sRecentsComponentCallbacks; static RecentsTaskLoadPlan sInstanceLoadPlan; @@ -104,6 +146,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta SystemServicesProxy mSystemServicesProxy; Handler mHandler; TaskStackListenerImpl mTaskStackListener; + RecentsOwnerEventProxyReceiver mProxyBroadcastReceiver; boolean mBootCompleted; boolean mStartAnimationTriggered; boolean mCanReuseTaskStackViews = true; @@ -123,7 +166,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta TaskStackView mDummyStackView; // Variables to keep track of if we need to start recents after binding - View mStatusBarView; boolean mTriggeredFromAltTab; long mLastToggleTime; @@ -136,30 +178,37 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta mTaskStackBounds = new Rect(); // Register the task stack listener - mTaskStackListener = new TaskStackListenerImpl(); + mTaskStackListener = new TaskStackListenerImpl(mHandler); mSystemServicesProxy.registerTaskStackListener(mTaskStackListener); + + // Only the owner has the callback to update the SysUI visibility flags, so all non-owner + // instances of AlternateRecentsComponent needs to notify the owner when the visibility + // changes. + if (mSystemServicesProxy.isForegroundUserOwner()) { + mProxyBroadcastReceiver = new RecentsOwnerEventProxyReceiver(); + IntentFilter filter = new IntentFilter(); + filter.addAction(AlternateRecentsComponent.ACTION_PROXY_NOTIFY_RECENTS_VISIBLITY_TO_OWNER); + mContext.registerReceiverAsUser(mProxyBroadcastReceiver, UserHandle.CURRENT, filter, + null, mHandler); + } + } + + /** Creates a new broadcast intent */ + static Intent createLocalBroadcastIntent(Context context, String action) { + Intent intent = new Intent(action); + intent.setPackage(context.getPackageName()); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | + Intent.FLAG_RECEIVER_FOREGROUND); + return intent; } + /** Initializes the Recents. */ + @ProxyFromPrimaryToCurrentUser public void onStart() { // Initialize some static datastructures TaskStackViewLayoutAlgorithm.initializeCurve(); // Load the header bar layout - reloadHeaderBarLayout(); - // Try and pre-emptively bind the search widget on startup to ensure that we - // have the right thumbnail bounds to animate to. - if (Constants.DebugFlags.App.EnableSearchLayout) { - // If there is no id, then bind a new search app widget - if (mConfig.searchBarAppWidgetId < 0) { - AppWidgetHost host = new RecentsAppWidgetHost(mContext, - Constants.Values.App.AppWidgetHostId); - Pair<Integer, AppWidgetProviderInfo> widgetInfo = - mSystemServicesProxy.bindSearchAppWidget(host); - if (widgetInfo != null) { - // Save the app widget id into the settings - mConfig.updateSearchBarAppWidgetId(mContext, widgetInfo.first); - } - } - } + reloadHeaderBarLayout(true); // When we start, preload the data associated with the previous recent tasks. // We can use a new plan since the caches will be the same. @@ -177,9 +226,19 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta mBootCompleted = true; } - /** Shows the recents */ - public void onShowRecents(boolean triggeredFromAltTab, View statusBarView) { - mStatusBarView = statusBarView; + /** Shows the Recents. */ + @ProxyFromPrimaryToCurrentUser + public void onShowRecents(boolean triggeredFromAltTab) { + if (mSystemServicesProxy.isForegroundUserOwner()) { + showRecents(triggeredFromAltTab); + } else { + Intent intent = createLocalBroadcastIntent(mContext, + RecentsUserEventProxyReceiver.ACTION_PROXY_SHOW_RECENTS_TO_USER); + intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, triggeredFromAltTab); + mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); + } + } + void showRecents(boolean triggeredFromAltTab) { mTriggeredFromAltTab = triggeredFromAltTab; try { @@ -189,16 +248,25 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } } - /** Hides the recents */ + /** Hides the Recents. */ + @ProxyFromPrimaryToCurrentUser public void onHideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { + if (mSystemServicesProxy.isForegroundUserOwner()) { + hideRecents(triggeredFromAltTab, triggeredFromHomeKey); + } else { + Intent intent = createLocalBroadcastIntent(mContext, + RecentsUserEventProxyReceiver.ACTION_PROXY_HIDE_RECENTS_TO_USER); + intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, triggeredFromAltTab); + intent.putExtra(EXTRA_TRIGGERED_FROM_HOME_KEY, triggeredFromHomeKey); + mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); + } + } + void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { if (mBootCompleted) { ActivityManager.RunningTaskInfo topTask = getTopMostTask(); if (topTask != null && isRecentsTopMost(topTask, null)) { // Notify recents to hide itself - Intent intent = new Intent(ACTION_HIDE_RECENTS_ACTIVITY); - intent.setPackage(mContext.getPackageName()); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | - Intent.FLAG_RECEIVER_FOREGROUND); + Intent intent = createLocalBroadcastIntent(mContext, ACTION_HIDE_RECENTS_ACTIVITY); intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, triggeredFromAltTab); intent.putExtra(EXTRA_TRIGGERED_FROM_HOME_KEY, triggeredFromHomeKey); mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); @@ -206,9 +274,18 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } } - /** Toggles the alternate recents activity */ - public void onToggleRecents(View statusBarView) { - mStatusBarView = statusBarView; + /** Toggles the Recents activity. */ + @ProxyFromPrimaryToCurrentUser + public void onToggleRecents() { + if (mSystemServicesProxy.isForegroundUserOwner()) { + toggleRecents(); + } else { + Intent intent = createLocalBroadcastIntent(mContext, + RecentsUserEventProxyReceiver.ACTION_PROXY_TOGGLE_RECENTS_TO_USER); + mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); + } + } + void toggleRecents() { mTriggeredFromAltTab = false; try { @@ -218,7 +295,18 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } } + /** Preloads info for the Recents activity. */ + @ProxyFromPrimaryToCurrentUser public void onPreloadRecents() { + if (mSystemServicesProxy.isForegroundUserOwner()) { + preloadRecents(); + } else { + Intent intent = createLocalBroadcastIntent(mContext, + RecentsUserEventProxyReceiver.ACTION_PROXY_PRELOAD_RECENTS_TO_USER); + mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); + } + } + void preloadRecents() { // Preload only the raw task list into a new load plan (which will be consumed by the // RecentsActivity) RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); @@ -309,15 +397,26 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta showRelativeAffiliatedTask(false); } + /** Updates on configuration change. */ + @ProxyFromPrimaryToCurrentUser public void onConfigurationChanged(Configuration newConfig) { + if (mSystemServicesProxy.isForegroundUserOwner()) { + configurationChanged(); + } else { + Intent intent = createLocalBroadcastIntent(mContext, + RecentsUserEventProxyReceiver.ACTION_PROXY_CONFIG_CHANGE_TO_USER); + mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); + } + } + void configurationChanged() { // Don't reuse task stack views if the configuration changes mCanReuseTaskStackViews = false; // Reload the header bar layout - reloadHeaderBarLayout(); + reloadHeaderBarLayout(false); } /** Prepares the header bar layout. */ - void reloadHeaderBarLayout() { + void reloadHeaderBarLayout(boolean reloadWidget) { Resources res = mContext.getResources(); mWindowRect = mSystemServicesProxy.getWindowRect(); mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); @@ -325,6 +424,10 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); mConfig = RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy); mConfig.updateOnConfigurationChange(); + if (reloadWidget) { + // Reload the widget id before we get the task stack bounds + reloadSearchBarAppWidget(mContext, mSystemServicesProxy); + } mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight, (mConfig.hasTransposedNavBar ? mNavBarWidth : 0), mTaskStackBounds); if (mConfig.isLandscape && mConfig.hasTransposedNavBar) { @@ -350,6 +453,24 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight); } + /** Prepares the search bar app widget */ + void reloadSearchBarAppWidget(Context context, SystemServicesProxy ssp) { + // Try and pre-emptively bind the search widget on startup to ensure that we + // have the right thumbnail bounds to animate to. + if (Constants.DebugFlags.App.EnableSearchLayout) { + // If there is no id, then bind a new search app widget + if (mConfig.searchBarAppWidgetId < 0) { + AppWidgetHost host = new RecentsAppWidgetHost(context, + Constants.Values.App.AppWidgetHostId); + Pair<Integer, AppWidgetProviderInfo> widgetInfo = ssp.bindSearchAppWidget(host); + if (widgetInfo != null) { + // Save the app widget id into the settings + mConfig.updateSearchBarAppWidgetId(context, widgetInfo.first); + } + } + } + } + /** Gets the top task. */ ActivityManager.RunningTaskInfo getTopMostTask() { SystemServicesProxy ssp = mSystemServicesProxy; @@ -397,10 +518,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta AtomicBoolean isTopTaskHome = new AtomicBoolean(true); if (topTask != null && isRecentsTopMost(topTask, isTopTaskHome)) { // Notify recents to toggle itself - Intent intent = new Intent(ACTION_TOGGLE_RECENTS_ACTIVITY); - intent.setPackage(mContext.getPackageName()); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | - Intent.FLAG_RECEIVER_FOREGROUND); + Intent intent = createLocalBroadcastIntent(mContext, ACTION_TOGGLE_RECENTS_ACTIVITY); mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); mLastToggleTime = SystemClock.elapsedRealtime(); return; @@ -474,7 +592,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } mStartAnimationTriggered = false; - return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView, + return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(), toTaskRect.height(), this); } @@ -623,7 +741,19 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta } /** Notifies the callbacks that the visibility of Recents has changed. */ - public static void notifyVisibilityChanged(boolean visible) { + @ProxyFromAnyToPrimaryUser + public static void notifyVisibilityChanged(Context context, SystemServicesProxy ssp, + boolean visible) { + if (ssp.isForegroundUserOwner()) { + visibilityChanged(visible); + } else { + Intent intent = createLocalBroadcastIntent(context, + ACTION_PROXY_NOTIFY_RECENTS_VISIBLITY_TO_OWNER); + intent.putExtra(EXTRA_RECENTS_VISIBILITY, visible); + context.sendBroadcastAsUser(intent, UserHandle.OWNER); + } + } + static void visibilityChanged(boolean visible) { if (sRecentsComponentCallbacks != null) { sRecentsComponentCallbacks.onVisibilityChanged(visible); } @@ -667,10 +797,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta }; // Send the broadcast to notify Recents that the animation has started - Intent intent = new Intent(ACTION_START_ENTER_ANIMATION); - intent.setPackage(mContext.getPackageName()); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | - Intent.FLAG_RECEIVER_FOREGROUND); + Intent intent = createLocalBroadcastIntent(mContext, ACTION_START_ENTER_ANIMATION); mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, fallbackReceiver, null, Activity.RESULT_CANCELED, null, null); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 6baff96..ee631f5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -434,7 +434,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView protected void onStart() { super.onStart(); mVisible = true; - AlternateRecentsComponent.notifyVisibilityChanged(true); + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + SystemServicesProxy ssp = loader.getSystemServicesProxy(); + AlternateRecentsComponent.notifyVisibilityChanged(this, ssp, true); // Register the broadcast receiver to handle messages from our service IntentFilter filter = new IntentFilter(); @@ -444,7 +446,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView registerReceiver(mServiceBroadcastReceiver, filter); // Register any broadcast receivers for the task loader - RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView); + loader.registerReceivers(this, mRecentsView); // Update the recent tasks updateRecentsTasks(getIntent()); @@ -454,7 +456,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView protected void onStop() { super.onStop(); mVisible = false; - AlternateRecentsComponent.notifyVisibilityChanged(false); + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + SystemServicesProxy ssp = loader.getSystemServicesProxy(); + AlternateRecentsComponent.notifyVisibilityChanged(this, ssp, false); // Notify the views that we are no longer visible mRecentsView.onRecentsHidden(); @@ -463,7 +467,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView unregisterReceiver(mServiceBroadcastReceiver); // Unregister any broadcast receivers for the task loader - RecentsTaskLoader.getInstance().unregisterReceivers(); + loader.unregisterReceivers(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsUserEventProxyReceiver.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsUserEventProxyReceiver.java new file mode 100644 index 0000000..236da5d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsUserEventProxyReceiver.java @@ -0,0 +1,70 @@ +/* + * 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.recents; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import com.android.systemui.recent.Recents; + + +/** + * A proxy for Recents events which happens strictly for non-owner users. + */ +public class RecentsUserEventProxyReceiver extends BroadcastReceiver { + final public static String ACTION_PROXY_SHOW_RECENTS_TO_USER = + "com.android.systemui.recents.action.SHOW_RECENTS_FOR_USER"; + final public static String ACTION_PROXY_HIDE_RECENTS_TO_USER = + "com.android.systemui.recents.action.HIDE_RECENTS_FOR_USER"; + final public static String ACTION_PROXY_TOGGLE_RECENTS_TO_USER = + "com.android.systemui.recents.action.TOGGLE_RECENTS_FOR_USER"; + final public static String ACTION_PROXY_PRELOAD_RECENTS_TO_USER = + "com.android.systemui.recents.action.PRELOAD_RECENTS_FOR_USER"; + final public static String ACTION_PROXY_CONFIG_CHANGE_TO_USER = + "com.android.systemui.recents.action.CONFIG_CHANGED_FOR_USER"; + + @Override + public void onReceive(Context context, Intent intent) { + AlternateRecentsComponent recents = Recents.getRecentsComponent( + context.getApplicationContext(), true); + switch (intent.getAction()) { + case ACTION_PROXY_SHOW_RECENTS_TO_USER: { + boolean triggeredFromAltTab = intent.getBooleanExtra( + AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false); + recents.showRecents(triggeredFromAltTab); + break; + } + case ACTION_PROXY_HIDE_RECENTS_TO_USER: { + boolean triggeredFromAltTab = intent.getBooleanExtra( + AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false); + boolean triggeredFromHome = intent.getBooleanExtra( + AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_HOME_KEY, false); + recents.hideRecents(triggeredFromAltTab, triggeredFromHome); + break; + } + case ACTION_PROXY_TOGGLE_RECENTS_TO_USER: + recents.toggleRecents(); + break; + case ACTION_PROXY_PRELOAD_RECENTS_TO_USER: + recents.preloadRecents(); + break; + case ACTION_PROXY_CONFIG_CHANGE_TO_USER: + recents.configurationChanged(); + break; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 3fbd5a6..542f21c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -49,14 +49,12 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import android.util.Pair; import android.view.Display; import android.view.DisplayInfo; -import android.view.IWindowManager; import android.view.SurfaceControl; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; @@ -396,6 +394,15 @@ public class SystemServicesProxy { } /** + * Returns whether the foreground user is the owner. + */ + public boolean isForegroundUserOwner() { + if (mAm == null) return false; + + return mAm.getCurrentUser() == UserHandle.USER_OWNER; + } + + /** * Resolves and returns the first Recents widget from the same package as the global * assist activity. */ diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 89aebe8..63a0cf6 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -3421,7 +3421,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return false; } - // Windows are ordered in z order so start from the botton and find + // Windows are ordered in z order so start from the bottom and find // the window of interest. After that all windows that cover it should // be subtracted from the resulting region. Note that for accessibility // we are returning only interactive windows. @@ -3439,7 +3439,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { windowInteractiveRegion = outRegion; continue; } - } else { + } else if (currentWindow.getType() + != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) { Rect currentWindowBounds = mTempRect; currentWindow.getBoundsInScreen(currentWindowBounds); if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) { diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 3117a17..ca376fd 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -535,15 +535,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Log.d(TAG, "Creating new ProfileServiceConnections object for" + " profile: " + bluetoothProfile); } - Intent intent = null; - if (bluetoothProfile == BluetoothProfile.HEADSET) { - intent = new Intent(IBluetoothHeadset.class.getName()); - } else { - return false; - } + + if (bluetoothProfile != BluetoothProfile.HEADSET) return false; + + Intent intent = new Intent(IBluetoothHeadset.class.getName()); psc = new ProfileServiceConnections(intent); + if (!psc.bindService()) return false; + mProfileServices.put(new Integer(bluetoothProfile), psc); - psc.bindService(); } } @@ -571,7 +570,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { synchronized (mProfileServices) { for (Integer i : mProfileServices.keySet()) { ProfileServiceConnections psc = mProfileServices.get(i); - mContext.unbindService(psc); + try { + mContext.unbindService(psc); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); + } psc.removeAllProxies(); } mProfileServices.clear(); @@ -596,16 +599,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mIntent = intent; } - private void bindService() { - if (mIntent != null && mService == null) { - if (!doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { - Log.w(TAG, "Unable to bind with intent: " + mIntent - + ". Triggering retry."); - } + private boolean bindService() { + if (mIntent != null && mService == null && + doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) { Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE); msg.obj = this; mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS); + return true; } + Log.w(TAG, "Unable to bind with intent: " + mIntent); + return false; } private void addProxy(IBluetoothProfileServiceConnection proxy) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1227148..844980b 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1841,7 +1841,9 @@ public final class ActivityManagerService extends ActivityManagerNative proc = mPendingPssProcesses.remove(0); procState = proc.pssProcState; lastPssTime = proc.lastPssTime; - if (proc.thread != null && procState == proc.setProcState) { + if (proc.thread != null && procState == proc.setProcState + && (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE) + < SystemClock.uptimeMillis()) { pid = proc.pid; } else { proc = null; @@ -17746,7 +17748,8 @@ public final class ActivityManagerService extends ActivityManagerNative + (app.nextPssTime-now) + ": " + app); } else { if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL) - && now > (app.lastStateTime+ProcessList.PSS_MIN_TIME_FROM_STATE_CHANGE))) { + && now > (app.lastStateTime+ProcessList.minTimeFromStateChange( + mTestPssMode)))) { requestPssLocked(app, app.setProcState); app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false, mTestPssMode, isSleeping(), now); @@ -18969,6 +18972,31 @@ public final class ActivityManagerService extends ActivityManagerNative } mUserSwitchObservers.finishBroadcast(); } + stopGuestUserIfBackground(); + } + + /** + * Stops the guest user if it has gone to the background. + */ + private void stopGuestUserIfBackground() { + synchronized (this) { + final int num = mUserLru.size(); + for (int i = 0; i < num; i++) { + Integer oldUserId = mUserLru.get(i); + UserStartedState oldUss = mStartedUsers.get(oldUserId); + if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId + || oldUss.mState == UserStartedState.STATE_STOPPING + || oldUss.mState == UserStartedState.STATE_SHUTDOWN) { + continue; + } + UserInfo userInfo = mUserManager.getUserInfo(oldUserId); + if (userInfo.isGuest()) { + // This is a user to be stopped. + stopUserLocked(oldUserId, null); + break; + } + } + } } void scheduleStartProfilesLocked() { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index aa86786..ae4af5f 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -238,7 +238,7 @@ final class ProcessList { if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { // Increase the high min-free levels for cached processes for 64-bit mOomMinFreeHigh[4] = (mOomMinFreeHigh[4]*3)/2; - mOomMinFreeHigh[5] = (mOomMinFreeHigh[5]*7)/8; + mOomMinFreeHigh[5] = (mOomMinFreeHigh[5]*7)/4; } for (int i=0; i<mOomAdj.length; i++) { @@ -411,7 +411,10 @@ final class ProcessList { sb.append(ramKb); } - // The minimum amount of time after a state change it is safe ro collect PSS. + // How long after a state change that it is safe to collect PSS without it being dirty. + public static final int PSS_SAFE_TIME_FROM_STATE_CHANGE = 1000; + + // The minimum time interval after a state change it is safe to collect PSS. public static final int PSS_MIN_TIME_FROM_STATE_CHANGE = 15*1000; // The maximum amount of time we want to go between PSS collections. @@ -441,6 +444,9 @@ final class ProcessList { // The amount of time until PSS when a cached process stays in the same state. private static final int PSS_SAME_CACHED_INTERVAL = 30*60*1000; + // The minimum time interval after a state change it is safe to collect PSS. + public static final int PSS_TEST_MIN_TIME_FROM_STATE_CHANGE = 10*1000; + // The amount of time during testing until PSS when a process first becomes top. private static final int PSS_TEST_FIRST_TOP_INTERVAL = 3*1000; @@ -548,6 +554,10 @@ final class ProcessList { return sProcStateToProcMem[procState1] != sProcStateToProcMem[procState2]; } + public static long minTimeFromStateChange(boolean test) { + return test ? PSS_TEST_MIN_TIME_FROM_STATE_CHANGE : PSS_MIN_TIME_FROM_STATE_CHANGE; + } + public static long computeNextPssTime(int procState, boolean first, boolean test, boolean sleeping, long now) { final long[] table = test diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index bb99916..650f0e2 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1028,6 +1028,7 @@ public class NotificationManagerService extends SystemService { ? mListenersDisablingEffects.valueAt(0).component : null; if (Objects.equals(suppressor, mEffectsSuppressor)) return; mEffectsSuppressor = suppressor; + mZenModeHelper.setEffectsSuppressed(suppressor != null); getContext().sendBroadcast(new Intent(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)); } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 012e22f..31d5cd7 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -17,6 +17,7 @@ package com.android.server.notification; import static android.media.AudioAttributes.USAGE_ALARM; +import static android.media.AudioAttributes.USAGE_NOTIFICATION; import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; import android.app.AppOpsManager; @@ -77,6 +78,7 @@ public class ZenModeHelper implements AudioManagerInternal.RingerModeDelegate { private ZenModeConfig mConfig; private AudioManagerInternal mAudioManager; private int mPreviousRingerMode = -1; + private boolean mEffectsSuppressed; public ZenModeHelper(Context context, Looper looper) { mContext = context; @@ -153,6 +155,12 @@ public class ZenModeHelper implements AudioManagerInternal.RingerModeDelegate { } } + public void setEffectsSuppressed(boolean effectsSuppressed) { + if (mEffectsSuppressed == effectsSuppressed) return; + mEffectsSuppressed = effectsSuppressed; + applyRestrictions(); + } + public boolean shouldIntercept(NotificationRecord record) { if (isSystem(record)) { return false; @@ -225,29 +233,35 @@ public class ZenModeHelper implements AudioManagerInternal.RingerModeDelegate { ZenLog.traceUpdateZenMode(oldMode, newMode); } mZenMode = newMode; + applyRestrictions(); + onZenUpdated(oldMode, newMode); + dispatchOnZenModeChanged(); + } + + private void applyRestrictions() { final boolean zen = mZenMode != Global.ZEN_MODE_OFF; - final String[] exceptionPackages = null; // none (for now) + + // notification restrictions + final boolean muteNotifications = mEffectsSuppressed; + applyRestrictions(muteNotifications, USAGE_NOTIFICATION); // call restrictions - final boolean muteCalls = zen && !mConfig.allowCalls; - mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_NOTIFICATION_RINGTONE, - muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, - exceptionPackages); - mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, USAGE_NOTIFICATION_RINGTONE, - muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, - exceptionPackages); + final boolean muteCalls = zen && !mConfig.allowCalls || mEffectsSuppressed; + applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE); // alarm restrictions final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; - mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_ALARM, - muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, + applyRestrictions(muteAlarms, USAGE_ALARM); + } + + private void applyRestrictions(boolean mute, int usage) { + final String[] exceptionPackages = null; // none (for now) + mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage, + mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, exceptionPackages); - mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, USAGE_ALARM, - muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, + mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage, + mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, exceptionPackages); - - onZenUpdated(oldMode, newMode); - dispatchOnZenModeChanged(); } public void dump(PrintWriter pw, String prefix) { @@ -257,6 +271,7 @@ public class ZenModeHelper implements AudioManagerInternal.RingerModeDelegate { pw.print(prefix); pw.print("mDefaultConfig="); pw.println(mDefaultConfig); pw.print(prefix); pw.print("mPreviousRingerMode="); pw.println(mPreviousRingerMode); pw.print(prefix); pw.print("mDefaultPhoneApp="); pw.println(mDefaultPhoneApp); + pw.print(prefix); pw.print("mEffectsSuppressed="); pw.println(mEffectsSuppressed); } public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException { diff --git a/services/core/java/com/android/server/wm/KeyguardDisableHandler.java b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java index c1420a8..37d811f 100644 --- a/services/core/java/com/android/server/wm/KeyguardDisableHandler.java +++ b/services/core/java/com/android/server/wm/KeyguardDisableHandler.java @@ -68,9 +68,18 @@ public class KeyguardDisableHandler extends Handler { break; case KEYGUARD_POLICY_CHANGED: - mPolicy.enableKeyguard(true); - // lazily evaluate this next time we're asked to disable keyguard mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; + if (mKeyguardTokenWatcher.isAcquired()) { + // If we are currently disabled we need to know if the keyguard + // should be re-enabled, so determine the allow state immediately. + mKeyguardTokenWatcher.updateAllowState(); + if (mAllowDisableKeyguard != ALLOW_DISABLE_YES) { + mPolicy.enableKeyguard(true); + } + } else { + // lazily evaluate this next time we're asked to disable keyguard + mPolicy.enableKeyguard(true); + } break; } } @@ -81,24 +90,28 @@ public class KeyguardDisableHandler extends Handler { super(handler, TAG); } - @Override - public void acquired() { + public void updateAllowState() { // We fail safe and prevent disabling keyguard in the unlikely event this gets // called before DevicePolicyManagerService has started. - if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) { - DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService( - Context.DEVICE_POLICY_SERVICE); - if (dpm != null) { - try { - mAllowDisableKeyguard = dpm.getPasswordQuality(null, - ActivityManagerNative.getDefault().getCurrentUser().id) - == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ? - ALLOW_DISABLE_YES : ALLOW_DISABLE_NO; - } catch (RemoteException re) { - // Nothing much we can do - } + DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService( + Context.DEVICE_POLICY_SERVICE); + if (dpm != null) { + try { + mAllowDisableKeyguard = dpm.getPasswordQuality(null, + ActivityManagerNative.getDefault().getCurrentUser().id) + == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ? + ALLOW_DISABLE_YES : ALLOW_DISABLE_NO; + } catch (RemoteException re) { + // Nothing much we can do } } + } + + @Override + public void acquired() { + if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) { + updateAllowState(); + } if (mAllowDisableKeyguard == ALLOW_DISABLE_YES) { mPolicy.enableKeyguard(false); } else { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 73e3213..d0ddeac 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -43,6 +43,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -3183,6 +3184,39 @@ public class TelephonyManager { } /** + * Override the roaming preference for the current ICCID. + * + * Using this call, the carrier app (see #hasCarrierPrivileges) can override + * the platform's notion of a network operator being considered roaming or not. + * The change only affects the ICCID that was active when this call was made. + * + * If null is passed as any of the input, the corresponding value is deleted. + * + * <p>Requires that the caller have carrier privilege. See #hasCarrierPrivileges. + * + * @param gsmRoamingList - List of MCCMNCs to be considered roaming for 3GPP RATs. + * @param gsmNonRoamingList - List of MCCMNCs to be considered not roaming for 3GPP RATs. + * @param cdmaRoamingList - List of SIDs to be considered roaming for 3GPP2 RATs. + * @param cdmaNonRoamingList - List of SIDs to be considered not roaming for 3GPP2 RATs. + * @return true if the operation was executed correctly. + * + * @hide + */ + public boolean setRoamingOverride(List<String> gsmRoamingList, + List<String> gsmNonRoamingList, List<String> cdmaRoamingList, + List<String> cdmaNonRoamingList) { + try { + return getITelephony().setRoamingOverride(gsmRoamingList, gsmNonRoamingList, + cdmaRoamingList, cdmaNonRoamingList); + } catch (RemoteException ex) { + Rlog.e(TAG, "setRoamingOverride RemoteException", ex); + } catch (NullPointerException ex) { + Rlog.e(TAG, "setRoamingOverride NPE", ex); + } + return false; + } + + /** * Expose the rest of ITelephony to @SystemApi */ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 4affad8..ca14ca4 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -792,6 +792,27 @@ interface ITelephony { boolean setOperatorBrandOverride(String brand); /** + * Override the roaming indicator for the current ICCID. + * + * Using this call, the carrier app (see #hasCarrierPrivileges) can override + * the platform's notion of a network operator being considered roaming or not. + * The change only affects the ICCID that was active when this call was made. + * + * If null is passed as any of the input, the corresponding value is deleted. + * + * <p>Requires that the caller have carrier privilege. See #hasCarrierPrivileges. + * + * @param gsmRoamingList - List of MCCMNCs to be considered roaming for 3GPP RATs. + * @param gsmNonRoamingList - List of MCCMNCs to be considered not roaming for 3GPP RATs. + * @param cdmaRoamingList - List of SIDs to be considered roaming for 3GPP2 RATs. + * @param cdmaNonRoamingList - List of SIDs to be considered not roaming for 3GPP2 RATs. + * @return true if the operation was executed correctly. + */ + boolean setRoamingOverride(in List<String> gsmRoamingList, + in List<String> gsmNonRoamingList, in List<String> cdmaRoamingList, + in List<String> cdmaNonRoamingList); + + /** * Returns the result and response from RIL for oem request * * @param oemReq the data is sent to ril. |
