diff options
322 files changed, 7907 insertions, 10086 deletions
diff --git a/Android.bp b/Android.bp index 7693a66fc1f7..7687270fc6f7 100644 --- a/Android.bp +++ b/Android.bp @@ -1417,10 +1417,6 @@ stubs_defaults { srcs_lib: "framework", srcs_lib_whitelist_dirs: frameworks_base_subdirs, srcs_lib_whitelist_pkgs: packages_to_document, - libs: [ - "ext", - "framework", - ], local_sourcepaths: frameworks_base_subdirs, installable: false, annotations_enabled: true, diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java index e2ef7a11b3a0..2fe0ee7cab57 100644 --- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java @@ -530,10 +530,10 @@ public class UserLifecycleTests { */ private void startApp(int userId, String packageName) throws RemoteException { final Context context = InstrumentationRegistry.getContext(); - final WaitResult result = ActivityTaskManager.getService().startActivityAndWait(null, null, - context.getPackageManager().getLaunchIntentForPackage(packageName), - null, null, null, 0, 0, null, null, - userId); + final WaitResult result = ActivityTaskManager.getService().startActivityAndWait(null, + context.getPackageName(), + context.getPackageManager().getLaunchIntentForPackage(packageName), null, null, + null, 0, 0, null, null, userId); attestTrue("User " + userId + " failed to start " + packageName, result.result == ActivityManager.START_SUCCESS); } diff --git a/api/current.txt b/api/current.txt index a7b38a5d5b10..aa772f1da24d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2810,6 +2810,14 @@ package android.accessibilityservice { method public void onClicked(android.accessibilityservice.AccessibilityButtonController); } + public final class AccessibilityGestureInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getDisplayId(); + method public int getGestureId(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.AccessibilityGestureInfo> CREATOR; + } + public abstract class AccessibilityService extends android.app.Service { ctor public AccessibilityService(); method public final void disableSelf(); @@ -2824,7 +2832,8 @@ package android.accessibilityservice { method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows(); method public abstract void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent); method public final android.os.IBinder onBind(android.content.Intent); - method protected boolean onGesture(int); + method @Deprecated protected boolean onGesture(int); + method public boolean onGesture(@NonNull android.accessibilityservice.AccessibilityGestureInfo); method public abstract void onInterrupt(); method protected boolean onKeyEvent(android.view.KeyEvent); method protected void onServiceConnected(); @@ -2966,6 +2975,7 @@ package android.accessibilityservice { } public final class GestureDescription { + method public int getDisplayId(); method public static long getMaxGestureDuration(); method public static int getMaxStrokeCount(); method public android.accessibilityservice.GestureDescription.StrokeDescription getStroke(@IntRange(from=0) int); @@ -2976,6 +2986,7 @@ package android.accessibilityservice { ctor public GestureDescription.Builder(); method public android.accessibilityservice.GestureDescription.Builder addStroke(@NonNull android.accessibilityservice.GestureDescription.StrokeDescription); method public android.accessibilityservice.GestureDescription build(); + method @NonNull public android.accessibilityservice.GestureDescription.Builder setDisplayId(int); } public static class GestureDescription.StrokeDescription { @@ -11757,6 +11768,9 @@ package android.content.pm { field public static final String FEATURE_SENSOR_RELATIVE_HUMIDITY = "android.hardware.sensor.relative_humidity"; field public static final String FEATURE_SENSOR_STEP_COUNTER = "android.hardware.sensor.stepcounter"; field public static final String FEATURE_SENSOR_STEP_DETECTOR = "android.hardware.sensor.stepdetector"; + field public static final String FEATURE_SE_OMAPI_ESE = "android.hardware.se.omapi.ese"; + field public static final String FEATURE_SE_OMAPI_SD = "android.hardware.se.omapi.sd"; + field public static final String FEATURE_SE_OMAPI_UICC = "android.hardware.se.omapi.uicc"; field public static final String FEATURE_SIP = "android.software.sip"; field public static final String FEATURE_SIP_VOIP = "android.software.sip.voip"; field public static final String FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore"; @@ -43991,6 +44005,7 @@ package android.telephony { public class CarrierConfigManager { method @Nullable public android.os.PersistableBundle getConfig(); + method @Nullable public android.os.PersistableBundle getConfigByComponentForSubId(String, int); method @Nullable public android.os.PersistableBundle getConfigForSubId(int); method public static boolean isConfigForIdentifiedCarrier(android.os.PersistableBundle); method public void notifyConfigChangedForSubId(int); @@ -44168,6 +44183,10 @@ package android.telephony { field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool"; } + public static final class CarrierConfigManager.Ims { + field public static final String KEY_PREFIX = "ims."; + } + public abstract class CellIdentity implements android.os.Parcelable { method public int describeContents(); method @Nullable public CharSequence getOperatorAlphaLong(); @@ -44350,6 +44369,7 @@ package android.telephony { method public int getBitErrorRate(); method public int getDbm(); method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel(); + method public int getRssi(); method public int getTimingAdvance(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthGsm> CREATOR; diff --git a/api/test-current.txt b/api/test-current.txt index b393fccdb366..8e6ff3019b0a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -32,6 +32,14 @@ package android { } +package android.accessibilityservice { + + public final class AccessibilityGestureInfo implements android.os.Parcelable { + ctor public AccessibilityGestureInfo(int, int); + } + +} + package android.animation { public class ValueAnimator extends android.animation.Animator { @@ -3028,6 +3036,7 @@ package android.util { field public static final String PERSIST_PREFIX = "persist.sys.fflag.override."; field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press"; field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer"; + field public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2"; } public class TimeUtils { diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 30f4ad4c5c69..db384baff4d7 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -63,6 +63,10 @@ #include "BootAnimation.h" +#define ANIM_PATH_MAX 255 +#define STR(x) #x +#define STRTO(x) STR(x) + namespace android { static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; @@ -96,7 +100,7 @@ static constexpr size_t FONT_NUM_ROWS = FONT_NUM_CHARS / FONT_NUM_COLS; static const int TEXT_CENTER_VALUE = INT_MAX; static const int TEXT_MISSING_VALUE = INT_MIN; static const char EXIT_PROP_NAME[] = "service.bootanim.exit"; -static const int ANIM_ENTRY_NAME_MAX = 256; +static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1; static constexpr size_t TEXT_POS_LEN_MAX = 16; // --------------------------------------------------------------------------- @@ -694,7 +698,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) animation.width = width; animation.height = height; animation.fps = fps; - } else if (sscanf(l, " %c %d %d %s #%6s %16s %16s", + } else if (sscanf(l, " %c %d %d %" STRTO(ANIM_PATH_MAX) "s #%6s %16s %16s", &pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) { //SLOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s", // pathType, count, pause, path, color, clockPos1, clockPos2); diff --git a/cmds/locksettings/TEST_MAPPING b/cmds/locksettings/TEST_MAPPING new file mode 100644 index 000000000000..c1cba5f7f22d --- /dev/null +++ b/cmds/locksettings/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsDevicePolicyManagerTestCases", + "options": [ + { + "include-annotation": "com.android.cts.devicepolicy.annotations.LockSettingsTest" + }, + { + "exclude-annotation": "android.platform.test.annotations.FlakyTest" + } + ] + } + ] +} diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index ceabd39aee8b..f6c72ea9d3b9 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -5309,6 +5309,9 @@ message NetworkDnsEventReported { // Additional pass-through fields opaque to statsd. // The DNS resolver Mainline module can add new fields here without requiring an OS update. optional android.stats.dnsresolver.DnsQueryEvents dns_query_events = 8 [(log_mode) = MODE_BYTES]; + + // The sample rate of DNS stats (to statsd) is 1/sampling_rate_denom. + optional int32 sampling_rate_denom = 9; } /** diff --git a/cmds/statsd/tools/dogfood/Android.bp b/cmds/statsd/tools/dogfood/Android.bp deleted file mode 100644 index bb494a6025af..000000000000 --- a/cmds/statsd/tools/dogfood/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2017 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. -// -// - -android_app { - name: "StatsdDogfood", - platform_apis: true, - - srcs: ["src/**/*.java"], - - resource_dirs: ["res"], - static_libs: [ - "platformprotoslite", - "statsdprotolite", - ], - - privileged: true, - dex_preopt: { - enabled: false, - }, - certificate: "platform", - optimize: { - enabled: false, - }, -} diff --git a/cmds/statsd/tools/dogfood/AndroidManifest.xml b/cmds/statsd/tools/dogfood/AndroidManifest.xml deleted file mode 100644 index 52673fbdcf92..000000000000 --- a/cmds/statsd/tools/dogfood/AndroidManifest.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.statsd.dogfood" - android:sharedUserId="android.uid.system" - android:versionCode="1" - android:versionName="1.0" > - - <uses-permission android:name="android.permission.DUMP" /> - - <application - android:allowBackup="true" - android:icon="@drawable/ic_launcher" - android:label="@string/app_name" > - <activity - android:name=".MainActivity" - android:label="@string/app_name" - android:launchMode="singleTop" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <service android:name=".MainActivity$ReceiverIntentService" android:exported="true" /> - </application> -</manifest> diff --git a/cmds/statsd/tools/dogfood/res/drawable-hdpi/ic_launcher.png b/cmds/statsd/tools/dogfood/res/drawable-hdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 55621cc1074f..000000000000 --- a/cmds/statsd/tools/dogfood/res/drawable-hdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/dogfood/res/drawable-mdpi/ic_launcher.png b/cmds/statsd/tools/dogfood/res/drawable-mdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 11ec2068be19..000000000000 --- a/cmds/statsd/tools/dogfood/res/drawable-mdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/dogfood/res/drawable-xhdpi/ic_launcher.png b/cmds/statsd/tools/dogfood/res/drawable-xhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 7c02b784aa5d..000000000000 --- a/cmds/statsd/tools/dogfood/res/drawable-xhdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/dogfood/res/drawable-xxhdpi/ic_launcher.png b/cmds/statsd/tools/dogfood/res/drawable-xxhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 915d91441349..000000000000 --- a/cmds/statsd/tools/dogfood/res/drawable-xxhdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/dogfood/res/layout/activity_main.xml b/cmds/statsd/tools/dogfood/res/layout/activity_main.xml deleted file mode 100644 index 784ed40ce2c2..000000000000 --- a/cmds/statsd/tools/dogfood/res/layout/activity_main.xml +++ /dev/null @@ -1,162 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, 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. -*/ ---> -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" > - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - - <Button - android:id="@+id/push_config" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@android:color/holo_green_light" - android:text="@string/push_config"/> - <Button - android:id="@+id/set_receiver" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@android:color/holo_green_light" - android:text="@string/set_receiver"/> - <Button - android:id="@+id/remove_receiver" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@android:color/holo_green_light" - android:text="@string/remove_receiver"/> - - <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <Button android:id="@+id/app_a_wake_lock_acquire1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_a_get_wl1"/> - <Button android:id="@+id/app_a_wake_lock_release1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_a_release_wl1"/> - </LinearLayout> - - <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <Button android:id="@+id/app_a_wake_lock_acquire2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_a_get_wl2"/> - <Button android:id="@+id/app_a_wake_lock_release2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_a_release_wl2"/> - </LinearLayout> - - <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <Button android:id="@+id/app_b_wake_lock_acquire1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_b_get_wl1"/> - <Button android:id="@+id/app_b_wake_lock_release1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_b_release_wl1"/> - </LinearLayout> - <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <Button android:id="@+id/app_b_wake_lock_acquire2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_b_get_wl2"/> - <Button android:id="@+id/app_b_wake_lock_release2" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/app_b_release_wl2"/> - </LinearLayout> - - <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <Button android:id="@+id/plug" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/plug"/> - - <Button android:id="@+id/unplug" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/unplug"/> - </LinearLayout> - - <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <Button android:id="@+id/screen_on" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/screen_on"/> - - <Button android:id="@+id/screen_off" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/screen_off"/> - </LinearLayout> - - <LinearLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - - <Button - android:id="@+id/custom_start" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/custom_start" /> - - <Button - android:id="@+id/custom_stop" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/custom_stop" /> - </LinearLayout> - - <Button android:id="@+id/dump" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@android:color/holo_purple" - android:text="@string/dump"/> - - <TextView - android:id="@+id/header" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/report_header"/> - - <TextView - android:id="@+id/report_text" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - </LinearLayout> - -</ScrollView>
\ No newline at end of file diff --git a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config b/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config deleted file mode 100644 index d05006124994..000000000000 --- a/cmds/statsd/tools/dogfood/res/raw/statsd_baseline_config +++ /dev/null @@ -1,109 +0,0 @@ -¹ÓõÕ¯¤”årÝèåâÕ»éÉ7¬ìŸ‘Ψê.–´šÄÁŒç¶ÚšäÑùôºZªÑ€¸ëÐé푘‹Ý™ûÆŽ6ˆ™ÁÖ΂õ›Ã¥¼à¨É—ÿQÝàåÈ߀äÍ@ÆÙÑ„ÓІ„èѿ̲±™¨lŸÄ€ìúˆÖü¶ú̳Šéâ‡ãà§ØÈË´Ù%óÓÚ«¹¼ÜyÛ®±ë¸«”º?¹•繡¸Œ€â鿨ŒÙœ®‘)çæ©Á”§äéîÀ‚Ò®ö‡.ÐÙ•°‹ÁÈy"'(WòóÀ–ðßæ¬ùÕàÀ™ýëZ”ÔÆ™Ž¤š¹»" -(2!ûÄߪæþªâÚ -V¢¦€¡’€Ç€¡ùÕàÀ™ýëZÈ‹ÄÂë¢Ä¯Ø" -(2 ª–¨Œ×ÿ¹¡k -V‡úÌòá㿘>ùÕàÀ™ýëZáž‹â‘Ý»ä" -(2!÷‘–ä–Œ¿¯ -WØõé¼ÃóÀàþùÕàÀ™ýëZ°ÔØùΣ‘¯" -(2!Ïä†÷ɯ -VÚœäÌþ½¬jùÕàÀ™ýëZ³Ö‰Ó¾ ½Ñ" -(2!Ÿ¡ªˆëôùÇ -V¨¾ñ≎̅ùÕàÀ™ýëZ“Ðåÿèåò?" -(2!½šòÐ䤿Œ -U…£²†µÜ‡‘_ùÕàÀ™ýëZñîôÒ‡¤´†z" -(2!é’¬¸ç¼‡Óª -K‘ã´¶üÅçúñ±Ë壆¨D”ÔÆ™Ž¤š¹»" -#(2ûÄߪæþªâÚ#Ië§ì·ºê•Æúñ±Ë壆¨DÈ‹ÄÂë¢Ä¯Ø" -#(2ª–¨Œ×ÿ¹¡k#JÙ¢Öúƒ†ðúñ±Ë壆¨Dáž‹â‘Ý»ä" -#(2÷‘–ä–Œ¿¯#JãýØåóªü)úñ±Ë壆¨D°ÔØùΣ‘¯" -#(2Ïä†÷ɯ#KËÅÝÇž¹Åãúñ±Ë壆¨D³Ö‰Ó¾ ½Ñ" -#(2Ÿ¡ªˆëôùÇ#Jɳ¸ó€„ø‘Ãúñ±Ë壆¨D“Ðåÿèåò?" -#(2½šòÐ䤿Œ#J•–ó«ðô¤Þïúñ±Ë壆¨DñîôÒ‡¤´†z" -#(2é’¬¸ç¼‡Óª#J•ºÔ¯•…Î’:›ºô¿Úó¾kŒÓÜ¢¾ÌÊ" -(2ûÄߪæþªâÚI»ÓòÓí‰àÖ -›ºô¿Úó¾kǮ›ŸÊŸäâ" -(2ª–¨Œ×ÿ¹¡kJÖÐük÷y›ºô¿Úó¾kÿ‚¾žÃ“’§õ" -(2÷‘–ä–Œ¿¯JøÿÊ“åøË¨›ºô¿Úó¾k˜ý˜‘¢ŒÐÀI" -(2Ïä†÷ɯKõß°—’ì¾×›ºô¿Úó¾kì‘áÒîŸÙÍá" -(2Ÿ¡ªˆëôùÇJà¸ëòä¥û݈›ºô¿Úó¾kôé‹¿¿¸ßÄ" -(2½šòÐ䤿ŒJУŒð†¬µÙ›ºô¿Úó¾k‰±Öйˆ–Ôõ" -(2é’¬¸ç¼‡ÓªK—ÍË é÷ÐM鮣öü©µŒÓÜ¢¾ÌÊ" -(2ûÄߪæþªâÚJÌŽë á«¡´{鮣öü©µÇ®Â›ŸÊŸäâ" -(2ª–¨Œ×ÿ¹¡kL˜†ŒÏØì¡‹³é®£öü©µÿ‚¾žÃ“’§õ" -(2÷‘–ä–Œ¿¯Ká°Ñàƒ½†¶ý鮣öü©µ˜ý˜‘¢ŒÐÀI" -(2Ïä†÷ɯKÛ”Ÿò§…ÂÁY鮣öü©µì‘áÒîŸÙÍá" -(2Ÿ¡ªˆëôùÇKϜݗÞç±ù¥é®£öü©µôé‹¿¿¸ßÄ" -(2½šòÐ䤿ŒKÚÖ•·‰–B鮣öü©µ‰±Öйˆ–Ôõ" -(2é’¬¸ç¼‡Óª,Ä®öèÀƒ‘âÌ¥•€†ÜÖ×AÐÙ•°‹ÁÈy" -(€õ»•÷¾ÓçȪŠéñðȃŹ~”‰àÉ®¶f"(2é’¬¸ç¼‡Óª2½šòÐ䤿Œ2Ÿ¡ªˆëôùÇLشͼá™þþæ¿É¶ˆœ‚æð±ûÄߪæþªâÚ" --(2ûÄߪæþªâÚ-JÉ¥˜‘Ûüˆ‹ò¿É¶ˆœ‚æð±ª–¨Œ×ÿ¹¡k" --(2ª–¨Œ×ÿ¹¡k-L¡©äÞ¨ô¶ø½¿É¶ˆœ‚æð±÷‘–ä–Œ¿¯" --(2÷‘–ä–Œ¿¯-L‡õÇþ¡¾ÚÈþ¿É¶ˆœ‚æð±Ïä†÷ɯ" --(2Ïä†÷ɯ-L—î«ãïÚ½û¬¿É¶ˆœ‚æð±Ÿ¡ªˆëôùÇ" --(2Ÿ¡ªˆëôùÇ-LñÍý‚ÿô¿É¶ˆœ‚æð±½šòÐ䤿Œ" --(2½šòÐ䤿Œ-K‹òʰ«»íè|¿É¶ˆœ‚æð±é’¬¸ç¼‡Óª" --(2é’¬¸ç¼‡Óª-"9äëæÚòœ§=̨…¥”ìãÏ‘N ÐÙ•°‹ÁÈy*‘N0@":šˆž‚ÎñÐ̨…¥”ìãÏ‘N ÐÙ•°‹ÁÈy*‘N0@":ù»Žôç¾ãˆÐ̨…¥”ìãÏ‘N ÐÙ•°‹ÁÈy*‘N0@"9›™›ŸÝ†—ãS̨…¥”ìãÏ‘N ÐÙ•°‹ÁÈy*‘N0@":‹ããùŸáŽôºßñ¼ûÌ•˜“N ÐÙ•°‹ÁÈy*“N0@":ç΀àë Œƒôºßñ¼ûÌ•˜“N ÐÙ•°‹ÁÈy*“N0@":™˜µøÖ²Äìõôºßñ¼ûÌ•˜“N ÐÙ•°‹ÁÈy*“N0@":¬Öœ¥¥ÃÆŒÑôºßñ¼ûÌ•˜“N ÐÙ•°‹ÁÈy*“N0@"5ôÇ™±¶Ï¢‘ò•™ÔéŠñ˜Èu›N ÐÙ•°‹ÁÈy*›N0@"4«÷µÿ󲂜e•™ÔéŠñ˜Èu›N ÐÙ•°‹ÁÈy*›N0@"4å¢úˆÑÙúý•™ÔéŠñ˜Èu›N ÐÙ•°‹ÁÈy*›N0@"+ž—Õõ‰î¶±~‡î‚ÒÔÊ´ËœN ÐÙ•°‹ÁÈy0@",‘ó‚³ïÙù¦‚‡î‚ÒÔÊ´ËœN ÐÙ•°‹ÁÈy0@"+òßù¥·«Äà;‡î‚ÒÔÊ´ËœN ÐÙ•°‹ÁÈy0@",ÓûÅñÒ¢ô§Â‡î‚ÒÔÊ´ËœN ÐÙ•°‹ÁÈy0@"+¨²°žò³ƒ¨R‡î‚ÒÔÊ´ËœN ÐÙ•°‹ÁÈy0@"+ÞìøݱþÖq‡î‚ÒÔÊ´ËœN ÐÙ•°‹ÁÈy0@",͉šæÜŽÄÀ‡î‚ÒÔÊ´ËœN ÐÙ•°‹ÁÈy0@"3Ä»±ê¾¸ô°˜þËÉÇåãÃ2 ÐÙ•°‹ÁÈy*0@"‰Ñ½Ëñɤ¡™a˜þËÉÇåãÃ2 ”‰àÉ®¶f*0:é’¬¸ç¼‡Óª:½šòÐ䤿Œ:Ÿ¡ªˆëôùÇ@":ÃêåÒýéó¦ï‘ŽÁ°×ËÇÅß–N ÐÙ•°‹ÁÈy*–N0@":Àš‚ÑÀí£Ï‹‘ŽÁ°×ËÇÅß–N ÐÙ•°‹ÁÈy*–N0@"9¾¢ðÛßÒëéø›²Ö·ÔÈšN ÐÙ•°‹ÁÈy*šN0@"9÷´ç鼯Š~½ ¤„¹®Ð§¨˜N ÐÙ•°‹ÁÈy*˜N0@2YÝæÆËò ‚ú‘»óÓ¤ãËÕ”ÔÆ™Ž¤š¹»"!ûÄߪæþªâÚ -(2 -82X°öòΪáŠþ„»óÓ¤ãËÕÈ‹ÄÂë¢Ä¯Ø" ª–¨Œ×ÿ¹¡k -(2 -82X°ç¦ùºŒó·0»óÓ¤ãËÕáž‹â‘Ý»ä"!÷‘–ä–Œ¿¯ -(2 -82Yôæï°Þ¼ ”»óÓ¤ãËÕ°ÔØùΣ‘¯"!Ïä†÷ɯ -(2 -82Y¡Î°Ãåüý»óÓ¤ãËÕ³Ö‰Ó¾ ½Ñ"!Ÿ¡ªˆëôùÇ -(2 -82XÕ¤ô®Ã£ÇÓÈ»óÓ¤ãËÕ“Ðåÿèåò?"!½šòÐ䤿Œ -(2 -82XÖÂªßøæÌÊ»óÓ¤ãËÕñîôÒ‡¤´†z"!é’¬¸ç¼‡Óª -(2 -825’ÌíûÍõ÷Æ»óÓ¤ãËÕ®Èùé€ù’±W(2 -82X²¹÷߆ŒÀ¶`»óÓ¤ãËÕ”ÔÆ™Ž¤š¹»"!ûÄߪæþªâÚ -(2 -82W÷ÞŸÉÔ ëÍd»óÓ¤ãËÕÈ‹ÄÂë¢Ä¯Ø" ª–¨Œ×ÿ¹¡k -(2 -82XäÁš´¤·ñì.»óÓ¤ãËÕáž‹â‘Ý»ä"!÷‘–ä–Œ¿¯ -(2 -82YîæÍçâ»óÓ¤ãËÕ°ÔØùΣ‘¯"!Ïä†÷ɯ -(2 -82Y˜²Ì´×³ìóÓ¤ãËÕ³Ö‰Ó¾ ½Ñ"!Ÿ¡ªˆëôùÇ -(2 -82W¾¯†‘§È“¿P»óÓ¤ãËÕ“Ðåÿèåò?"!½šòÐ䤿Œ -(2 -82XÂÀ¶òšË˜‚ð»óÓ¤ãËÕñîôÒ‡¤´†z"!é’¬¸ç¼‡Óª -(2 -82U—îïÛ²¸¸†µ»óÓ¤ãËÕ”ÔÆ™Ž¤š¹»"!ûÄߪæþªâÚ -(2 -82Tû¯ûû²¶ýñ§»óÓ¤ãËÕÈ‹ÄÂë¢Ä¯Ø" ª–¨Œ×ÿ¹¡k -(2 -82T†ñù™ŸÈ¨«»óÓ¤ãËÕáž‹â‘Ý»ä"!÷‘–ä–Œ¿¯ -(2 -82T҈πŸ¯‰ŠD»óÓ¤ãËÕ°ÔØùΣ‘¯"!Ïä†÷ɯ -(2 -82Uš¤Ë„阿ö†»óÓ¤ãËÕ³Ö‰Ó¾ ½Ñ"!Ÿ¡ªˆëôùÇ -(2 -82SË©ËÞ¯öÈÞ&»óÓ¤ãËÕ“Ðåÿèåò?"!½šòÐ䤿Œ -(2 -82TάóýᔺèÞ»óÓ¤ãËÕñîôÒ‡¤´†z"!é’¬¸ç¼‡Óª -(2 -82#àšÉ±ûÿ±»óÓ¤ãËÕ®Èùé€ù’±W(82#ÞžÞïƒ÷“…±œ–±ÃŸ€ÀâFÐÙ•°‹ÁÈy(82"䣞ƒƒ¿Èòrœ–±ÃŸ€ÀâFÐÙ•°‹ÁÈy(82*¦‚ó©ÂÊÓŒ3œ–±ÃŸ€ÀâFÐÙ•°‹ÁÈy(2%82*ÅМ½à®ÄŠœ–±ÃŸ€ÀâFÐÙ•°‹ÁÈy(2%82"‡è‘²†ÙÓÂ+œ–±ÃŸ€ÀâFÐÙ•°‹ÁÈy(82J›»ÜŽáø©ÔӈƄת¶£«ŒÓÜ¢¾ÌÊ"ûÄߪæþªâÚ'(2'82H®Ñä‚Òš„ÝqˆÆ„ת¶£«Ç®Â›ŸÊŸäâ"ª–¨Œ×ÿ¹¡k'(2'82JêýÂÄ…Œ™ÉˆƄת¶£«ÿ‚¾žÃ“’§õ"÷‘–ä–Œ¿¯'(2'82Iâ븛ÚðÖóˆÆ„×ª¶£«˜ý˜‘¢ŒÐÀI"Ïä†÷ɯ'(2'82Iÿ±å¨ ïÉKˆÆ„ת¶£«ì‘áÒîŸÙÍá"Ÿ¡ªˆëôùÇ'(2'82Hý©ëÞ¥é÷“\ˆÆ„ת¶£«ôé‹¿¿¸ßÄ"½šòÐ䤿Œ'(2'82JÁ°Õ즊ý…¯ˆÆ„ת¶£«‰±Öйˆ–Ôõ"é’¬¸ç¼‡Óª'(2'82ƒ˜Êã•ÿÊÙÚ·æúŸÌ½‚¡”‰àÉ®¶f"é’¬¸ç¼‡Óª"½šòÐ䤿Œ"Ÿ¡ªˆëôùÇ(282‚ÊùÑèÂóžàY·æúŸÌ½‚¡”‰àÉ®¶f"é’¬¸ç¼‡Óª"½šòÐ䤿Œ"Ÿ¡ªˆëôùÇ(282MÚËñ´ä‡¼Ä'ª ÿçû¤é刌ÓÜ¢¾ÌÊ"ûÄߪæþªâÚ(2 -82LŽÏ—ꤦݯ5ª ÿçû¤éåˆÇ®Â›ŸÊŸäâ"ª–¨Œ×ÿ¹¡k(2 -82Nø‚ÍÁœÆÚª ÿçû¤éåˆÿ‚¾žÃ“’§õ"÷‘–ä–Œ¿¯(2 -82LŸ¿ŽöåèÆ)ª ÿçû¤é刘ý˜‘¢ŒÐÀI"Ïä†÷ɯ(2 -82NþÝÒÿ§Ù¡±˜ª ÿçû¤éåˆì‘áÒîŸÙÍá"Ÿ¡ªˆëôùÇ(2 -82M³Ñ×饊ÿ¦ª ÿçû¤éåˆôé‹¿¿¸ßÄ"½šòÐ䤿Œ(2 -82M–ÎÜ‹ó¯Ë„ª ÿçû¤é刉±Öйˆ–Ôõ"é’¬¸ç¼‡Óª(2 -82ƒÍê´ýÞÁöª ÿçû¤é刔‰àÉ®¶f"é’¬¸ç¼‡Óª"½šòÐ䤿Œ"Ÿ¡ªˆëôùÇ(282,Ü›ä¤ö¸Åˆºª ÿçû¤éåˆÐÙ•°‹ÁÈy(282+Ù¼‡úýõ‰—êâÓ»ä¾ÙÙ9ÐÙ•°‹ÁÈy(282.ƒÚæË›Õ²“^âÓ»ä¾ÙÙ9ÐÙ•°‹ÁÈy(2 -82/òìšÀ·ÄŒÃ#óª·Žð–äÑŠÐÙ•°‹ÁÈy(2 -82+¢ØþËÄÝßíyóª·Žð–äÑŠÐÙ•°‹ÁÈy(282"йʢäÞ†#½³ úùš±KÐÙ•°‹ÁÈy(82I¾Œ…û±ªÓþν³ úùš±KŒÓÜ¢¾ÌÊ"ûÄߪæþªâÚ(282HÞûÅŠëŽî½³ úùš±KǮ›ŸÊŸäâ"ª–¨Œ×ÿ¹¡k(282HÚÇÍý›ôÍô_½³ úùš±Kÿ‚¾žÃ“’§õ"÷‘–ä–Œ¿¯(282Gá”ܰ§¼Üï{½³ úùš±K˜ý˜‘¢ŒÐÀI"Ïä†÷ɯ(282IŒú’ìÌšŒÿ½³ úùš±Kì‘áÒîŸÙÍá"Ÿ¡ªˆëôùÇ(282HðÒ¬¼ïˆâ½³ úùš±Kôé‹¿¿¸ßÄ"½šòÐ䤿Œ(282Hˆ¼ÂÁŒ‚ªŠE½³ úùš±K‰±Öйˆ–Ôõ"é’¬¸ç¼‡Óª(282 ðÚžºÖèà몖¨Œ×ÿ¹¡k(282"…ïèÙŸåóþÎûÄߪæþªâÚ(282!ÆÉ¨‡âž¯‰÷‘–ä–Œ¿¯(282"Õ™õê×Ì·›‹Ïä†÷ɯ(282!Þíó¾ó¿ÚªˆëôùÇ(282!ž¥ÌÔѾۛL½šòÐ䤿Œ(282!„±ÂææÄÁOé’¬¸ç¼‡Óª(282+¦‚ýª¬¢˜þǪ–¨Œ×ÿ¹¡kÐÙ•°‹ÁÈy(282+Ó®¿Œïɳ=ûÄߪæþªâÚÐÙ•°‹ÁÈy(282+ØŽ„Øø¨²c÷‘–ä–Œ¿¯ÐÙ•°‹ÁÈy(282,ýŒ®ê£ÀËŠÏä†÷ɯÐÙ•°‹ÁÈy(282+’ÐÝç’묩uŸ¡ªˆëôùÇÐÙ•°‹ÁÈy(282,ÌÅ„„ŒúÔÞ ½šòÐ䤿ŒÐÙ•°‹ÁÈy(282,ÿªØ¦ƒ®èý»é’¬¸ç¼‡ÓªÐÙ•°‹ÁÈy(282#©Ô†«¹ÛÈÊœä”Û›ÅËèÄÐÙ•°‹ÁÈy(82,‡¼ã™“ЧӜä”Û›ÅËèÄÐÙ•°‹ÁÈy(282#ëÜÄêÖª©ÞùÃýب°Ï=ÐÙ•°‹ÁÈy(82I¬Í˜ÝïÚÈéùÃýب°Ï=ŒÓÜ¢¾ÌÊ"ûÄߪæþªâÚ(282Hã;ܲÍË®øùÃýب°Ï=Ǯ›ŸÊŸäâ"ª–¨Œ×ÿ¹¡k(282IÌ™¹ý¢ÞúŒ…ùÃýب°Ï=ÿ‚¾žÃ“’§õ"÷‘–ä–Œ¿¯(282GÚ´¯Ðèà £YùÃýب°Ï=˜ý˜‘¢ŒÐÀI"Ïä†÷ɯ(282IƒÈæÑ€¸µ§µùÃýب°Ï=ì‘áÒîŸÙÍá"Ÿ¡ªˆëôùÇ(282Gׇã ÉÈùÃýب°Ï=ôé‹¿¿¸ßÄ"½šòÐ䤿Œ(282HÁµÏ›é¥¸ãUùÃýب°Ï=‰±Öйˆ–Ôõ"é’¬¸ç¼‡Óª(282"§±¿Œ·¾íé„ò݃‰…Ï™sÐÙ•°‹ÁÈy(82I®‰Å„ÿ··„ò݃‰…Ï™sŒÓÜ¢¾ÌÊ"ûÄߪæþªâÚ(282H°ªåÛòÿ™˜„ò݃‰…Ï™sǮ›ŸÊŸäâ"ª–¨Œ×ÿ¹¡k(282HÖïˆÇ÷ðî’ -„ò݃‰…Ï™sÿ‚¾žÃ“’§õ"÷‘–ä–Œ¿¯(282Gæü•о°‹„ò݃‰…Ï™s˜ý˜‘¢ŒÐÀI"Ïä†÷ɯ(282HáŒêË ûÜÝ„ò݃‰…Ï™sì‘áÒîŸÙÍá"Ÿ¡ªˆëôùÇ(282GµüŒºÊ¥„ò݃‰…Ï™sôé‹¿¿¸ßÄ"½šòÐ䤿Œ(282HÏææŸÞñ˜È'„ò݃‰…Ï™s‰±Öйˆ–Ôõ"é’¬¸ç¼‡Óª(282#䪧¸ëð»ÍÖ“®ß®þÏ¿ÐÙ•°‹ÁÈy(82HâÈòŸ‚Ϫ¶;“®ß®þÏ¿ŒÓÜ¢¾ÌÊ"ûÄߪæþªâÚ(282GÅöôŽåËà@“®ß®þϿǮ›ŸÊŸäâ"ª–¨Œ×ÿ¹¡k(282H±¤ñþÜÀ«‡-“®ß®þÏ¿ÿ‚¾žÃ“’§õ"÷‘–ä–Œ¿¯(282GЇ¶ÇéíËI“®ß®þÏ¿˜ý˜‘¢ŒÐÀI"Ïä†÷ɯ(282H¶ÛŽˆÊÜÇÔ -“®ß®þÏ¿ì‘áÒîŸÙÍá"Ÿ¡ªˆëôùÇ(282Gñå°ì’³¯Ç“®ß®þÏ¿ôé‹¿¿¸ßÄ"½šòÐ䤿Œ(282H¥×©ë¹ÖÕÅb“®ß®þÏ¿‰±Öйˆ–Ôõ"é’¬¸ç¼‡Óª(282#¼ù´–ºîª¡Ÿ¤øÝŽ£î“KÐÙ•°‹ÁÈy(82H…üÖ½ßÇЃqŸ¤øÝŽ£î“KŒÓÜ¢¾ÌÊ"ûÄߪæþªâÚ(282GÀê÷ÅÒ×´øŸ¤øÝŽ£î“KǮ›ŸÊŸäâ"ª–¨Œ×ÿ¹¡k(282Iô ¨øÍ¹€Ÿ¤øÝŽ£î“Kÿ‚¾žÃ“’§õ"÷‘–ä–Œ¿¯(282HÍÆýö®£ÏåËŸ¤øÝŽ£î“K˜ý˜‘¢ŒÐÀI"Ïä†÷ɯ(282H¿¾Š “ʽ៤øÝŽ£î“Kì‘áÒîŸÙÍá"Ÿ¡ªˆëôùÇ(282GºÉ¬¦“ÆçÜpŸ¤øÝŽ£î“Kôé‹¿¿¸ßÄ"½šòÐ䤿Œ(282H•úŸþî¯ø6Ÿ¤øÝŽ£î“K‰±Öйˆ–Ôõ"é’¬¸ç¼‡Óª(28:â鿨ŒÙœ®‘*:ÔØ’¯—꓌’ („:ðÿÈ€ÀíÐð© (¬:ì¹ó¢â¯¢ÚÌ (Ü:ôïÆ þ©ƒ„ø (À:õµ…çÈηŽB (¤
:¸Î½Èìù„ (:¶›èõÖð®÷m (è:¨ÆºÀõµÈï¹ (” -:ãï©Ê½˜š¡® (¼:¥Ã¯œí…â¥w (ø -:å½ÈÂÏò“Þó (ˆ:¶Æèܦ™¥ìß( -( -( -( -( -B.ª ÿçû¤éåˆ!ÂŒÝëð ¢Ý›ºô¿Úó¾k2 -B"󄽾؜ߞ}™ºŽÔ–í”"žÈ¶ž•ÞŠè( -B-âÓ»ä¾ÙÙ9!µêЊîÄa鮣öü©µ2 -B,·æúŸÌ½‚¡ûó⿼‘ÿÿƒ«ŸˆÇŽ¿¡ diff --git a/cmds/statsd/tools/dogfood/res/values/strings.xml b/cmds/statsd/tools/dogfood/res/values/strings.xml deleted file mode 100644 index 60948a181a1b..000000000000 --- a/cmds/statsd/tools/dogfood/res/values/strings.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<resources> - - <string name="app_name">Statsd Dogfood</string> - - <string name="statsd_running">Statsd Running</string> - <string name="statsd_not_running">Statsd NOT Running</string> - - <string name="push_config">Push baseline config</string> - <string name="set_receiver">Set pendingintent</string> - <string name="remove_receiver">Remove pendingintent</string> - - <string name="app_a_foreground">App A foreground</string> - <string name="app_b_foreground">App B foreground</string> - - - <string name="app_a_get_wl1">App A get wl_1</string> - <string name="app_a_release_wl1">App A release wl_1</string> - - <string name="app_a_get_wl2">App A get wl_2</string> - <string name="app_a_release_wl2">App A release wl_2</string> - - <string name="app_b_get_wl1">App B get wl_1</string> - <string name="app_b_release_wl1">App B release wl_1</string> - - <string name="app_b_get_wl2">App B get wl_2</string> - <string name="app_b_release_wl2">App B release wl_2</string> - - <string name="plug">Plug</string> - <string name="unplug">Unplug</string> - - <string name="screen_on">Screen On</string> - <string name="screen_off">Screen Off</string> - - <string name="custom_start">App hook start</string> - <string name="custom_stop">App hook stop</string> - - <string name="dump">DumpReport</string> - <string name="report_header">Report details</string> -</resources> diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java deleted file mode 100644 index b6b16e40a4b2..000000000000 --- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/DisplayProtoUtils.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.dogfood; - -import android.text.format.DateFormat; - -import com.android.os.StatsLog; - -import java.util.List; - -public class DisplayProtoUtils { - public static void displayLogReport(StringBuilder sb, StatsLog.ConfigMetricsReportList reports) { - sb.append("ConfigKey: "); - if (reports.hasConfigKey()) { - com.android.os.StatsLog.ConfigMetricsReportList.ConfigKey key = reports.getConfigKey(); - sb.append("\tuid: ").append(key.getUid()).append(" name: ").append(key.getId()) - .append("\n"); - } - - for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) { - sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n"); - sb.append("Last report time:").append(getDateStr(report.getLastReportElapsedNanos())). - append("\n"); - sb.append("Current report time:").append(getDateStr(report.getCurrentReportElapsedNanos())). - append("\n"); - for (StatsLog.StatsLogReport log : report.getMetricsList()) { - sb.append("\n\n"); - sb.append("metric id: ").append(log.getMetricId()).append("\n"); - - switch (log.getDataCase()) { - case DURATION_METRICS: - sb.append("Duration metric data\n"); - displayDurationMetricData(sb, log); - break; - case EVENT_METRICS: - sb.append("Event metric data\n"); - displayEventMetricData(sb, log); - break; - case COUNT_METRICS: - sb.append("Count metric data\n"); - displayCountMetricData(sb, log); - break; - case GAUGE_METRICS: - sb.append("Gauge metric data\n"); - displayGaugeMetricData(sb, log); - break; - case VALUE_METRICS: - sb.append("Value metric data\n"); - displayValueMetricData(sb, log); - break; - case DATA_NOT_SET: - sb.append("No metric data\n"); - break; - } - } - } - } - - public static String getDateStr(long nanoSec) { - return DateFormat.format("dd/MM hh:mm:ss", nanoSec/1000000).toString(); - } - - private static void displayDimension(StringBuilder sb, StatsLog.DimensionsValue dimensionValue) { - sb.append(dimensionValue.getField()).append(":"); - if (dimensionValue.hasValueBool()) { - sb.append(dimensionValue.getValueBool()); - } else if (dimensionValue.hasValueFloat()) { - sb.append(dimensionValue.getValueFloat()); - } else if (dimensionValue.hasValueInt()) { - sb.append(dimensionValue.getValueInt()); - } else if (dimensionValue.hasValueStr()) { - sb.append(dimensionValue.getValueStr()); - } else if (dimensionValue.hasValueTuple()) { - sb.append("{"); - for (StatsLog.DimensionsValue child : - dimensionValue.getValueTuple().getDimensionsValueList()) { - displayDimension(sb, child); - } - sb.append("}"); - } - sb.append(" "); - } - - public static void displayDurationMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - StatsLog.StatsLogReport.DurationMetricDataWrapper durationMetricDataWrapper - = log.getDurationMetrics(); - sb.append("Dimension size: ").append(durationMetricDataWrapper.getDataCount()).append("\n"); - for (StatsLog.DurationMetricData duration : durationMetricDataWrapper.getDataList()) { - sb.append("dimension_in_what: "); - displayDimension(sb, duration.getDimensionsInWhat()); - sb.append("\n"); - if (duration.hasDimensionsInCondition()) { - sb.append("dimension_in_condition: "); - displayDimension(sb, duration.getDimensionsInCondition()); - sb.append("\n"); - } - - for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") - .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") - .append(info.getDurationNanos()).append(" ns\n"); - } - } - } - - public static void displayEventMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Contains ").append(log.getEventMetrics().getDataCount()).append(" events\n"); - StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper = - log.getEventMetrics(); - for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) { - sb.append(getDateStr(event.getElapsedTimestampNanos())).append(": "); - sb.append(event.getAtom().getPushedCase().toString()).append("\n"); - } - } - - public static void displayCountMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - StatsLog.StatsLogReport.CountMetricDataWrapper countMetricDataWrapper - = log.getCountMetrics(); - sb.append("Dimension size: ").append(countMetricDataWrapper.getDataCount()).append("\n"); - for (StatsLog.CountMetricData count : countMetricDataWrapper.getDataList()) { - sb.append("dimension_in_what: "); - displayDimension(sb, count.getDimensionsInWhat()); - sb.append("\n"); - if (count.hasDimensionsInCondition()) { - sb.append("dimension_in_condition: "); - displayDimension(sb, count.getDimensionsInCondition()); - sb.append("\n"); - } - - for (StatsLog.CountBucketInfo info : count.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") - .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") - .append(info.getCount()).append("\n"); - } - } - } - - public static void displayGaugeMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Display me!"); - } - - public static void displayValueMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Display me!"); - } -} diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java deleted file mode 100644 index 4f4dd011e419..000000000000 --- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.dogfood; - -import android.app.Activity; -import android.app.PendingIntent; -import android.app.IntentService; -import android.app.StatsManager; -import android.app.StatsManager.StatsUnavailableException; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.os.Bundle; -import android.util.Log; -import android.util.StatsLog; -import android.view.View; -import android.widget.TextView; -import android.widget.Toast; -import android.os.IStatsManager; -import android.os.ServiceManager; - -import java.io.InputStream; - -import static com.android.statsd.dogfood.DisplayProtoUtils.displayLogReport; - -public class MainActivity extends Activity { - private final static String TAG = "StatsdDogfood"; - private final static long CONFIG_ID = 987654321; - - final int[] mUids = {11111111, 2222222}; - StatsManager mStatsManager; - TextView mReportText; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.activity_main); - - findViewById(R.id.app_a_wake_lock_acquire1).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockAcquire(0, "wl_1"); - } - }); - - findViewById(R.id.app_b_wake_lock_acquire1).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockAcquire(1, "wl_1"); - } - }); - - findViewById(R.id.app_a_wake_lock_acquire2).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockAcquire(0, "wl_2"); - } - }); - - findViewById(R.id.app_b_wake_lock_acquire2).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockAcquire(1, "wl_2"); - } - }); - - findViewById(R.id.app_a_wake_lock_release1).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockRelease(0, "wl_1"); - } - }); - - - findViewById(R.id.app_b_wake_lock_release1).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockRelease(1, "wl_1"); - } - }); - - findViewById(R.id.app_a_wake_lock_release2).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockRelease(0, "wl_2"); - } - }); - - - findViewById(R.id.app_b_wake_lock_release2).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - onWakeLockRelease(1, "wl_2"); - } - }); - - - findViewById(R.id.plug).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, - StatsLog.PLUGGED_STATE_CHANGED__STATE__BATTERY_PLUGGED_AC); - } - }); - - findViewById(R.id.unplug).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - StatsLog.write(StatsLog.PLUGGED_STATE_CHANGED, - StatsLog.PLUGGED_STATE_CHANGED__STATE__BATTERY_PLUGGED_NONE); - } - }); - - findViewById(R.id.screen_on).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_ON); - } - }); - - findViewById(R.id.screen_off).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF); - } - }); - - findViewById(R.id.custom_start).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - StatsLog.logStart(8); - } - }); - - findViewById(R.id.custom_stop).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - StatsLog.logStop(8); - } - }); - - mReportText = (TextView) findViewById(R.id.report_text); - - findViewById(R.id.dump).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (!statsdRunning()) { - return; - } - if (mStatsManager != null) { - try { - byte[] data = mStatsManager.getReports(CONFIG_ID); - if (data != null) { - displayData(data); - return; - } - } catch (StatsUnavailableException e) { - Log.e(TAG, "Failed to get data from statsd", e); - } - mReportText.setText("Failed!"); - } - } - }); - - findViewById(R.id.push_config).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - if (!statsdRunning()) { - return; - } - Resources res = getResources(); - InputStream inputStream = res.openRawResource(R.raw.statsd_baseline_config); - - byte[] config = new byte[inputStream.available()]; - inputStream.read(config); - if (mStatsManager != null) { - try { - mStatsManager.addConfig(CONFIG_ID, config); - Toast.makeText( - MainActivity.this, "Config pushed", Toast.LENGTH_LONG).show(); - } catch (StatsUnavailableException | IllegalArgumentException e) { - Toast.makeText(MainActivity.this, "Config push FAILED!", - Toast.LENGTH_LONG).show(); - } - } - } catch (Exception e) { - Toast.makeText(MainActivity.this, "failed to read config", Toast.LENGTH_LONG); - } - } - }); - - PendingIntent pi = PendingIntent.getService(this, 0, - new Intent(this, ReceiverIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT); - findViewById(R.id.set_receiver).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - if (!statsdRunning()) { - return; - } - if (mStatsManager != null) { - try { - mStatsManager.setFetchReportsOperation(pi, CONFIG_ID); - Toast.makeText(MainActivity.this, - "Receiver specified to pending intent", Toast.LENGTH_LONG) - .show(); - } catch (StatsUnavailableException e) { - Toast.makeText(MainActivity.this, "Statsd did not set receiver", - Toast.LENGTH_LONG) - .show(); - } - } - } catch (Exception e) { - Toast.makeText(MainActivity.this, "failed to set receiver", Toast.LENGTH_LONG); - } - } - }); - findViewById(R.id.remove_receiver).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - if (!statsdRunning()) { - return; - } - if (mStatsManager != null) { - try { - mStatsManager.setFetchReportsOperation(null, CONFIG_ID); - Toast.makeText(MainActivity.this, "Receiver remove", Toast.LENGTH_LONG) - .show(); - } catch (StatsUnavailableException e) { - Toast.makeText(MainActivity.this, "Statsd did not remove receiver", - Toast.LENGTH_LONG) - .show(); - } - } - } catch (Exception e) { - Toast.makeText( - MainActivity.this, "failed to remove receiver", Toast.LENGTH_LONG); - } - } - }); - mStatsManager = (StatsManager) getSystemService("stats"); - } - - private boolean statsdRunning() { - if (IStatsManager.Stub.asInterface(ServiceManager.getService("stats")) == null) { - Log.d(TAG, "Statsd not running"); - Toast.makeText(MainActivity.this, "Statsd NOT running!", Toast.LENGTH_LONG).show(); - return false; - } - return true; - } - - @Override - public void onNewIntent(Intent intent) { - Log.d(TAG, "new intent: " + intent.getIntExtra("pkg", 0)); - int pkg = intent.getIntExtra("pkg", 0); - String name = intent.getStringExtra("name"); - if (intent.hasExtra("acquire")) { - onWakeLockAcquire(pkg, name); - } else if (intent.hasExtra("release")) { - onWakeLockRelease(pkg, name); - } - } - - private void displayData(byte[] data) { - com.android.os.StatsLog.ConfigMetricsReportList reports = null; - boolean good = false; - if (data != null) { - try { - reports = com.android.os.StatsLog.ConfigMetricsReportList.parseFrom(data); - good = true; - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - // display it in the text view. - } - } - int size = data == null ? 0 : data.length; - StringBuilder sb = new StringBuilder(); - sb.append(good ? "Proto parsing OK!" : "Proto parsing Error!"); - sb.append(" size:").append(size).append("\n"); - - if (good && reports != null) { - displayLogReport(sb, reports); - mReportText.setText(sb.toString()); - } - } - - - private void onWakeLockAcquire(int id, String name) { - if (id > 1) { - Log.d(TAG, "invalid pkg id"); - return; - } - int[] uids = new int[]{mUids[id]}; - String[] tags = new String[]{"acquire"}; - StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, - StatsLog.WAKELOCK_STATE_CHANGED__TYPE__PARTIAL_WAKE_LOCK, name, - StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE); - StringBuilder sb = new StringBuilder(); - sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0) - .append(", ").append(name).append(", 1);"); - Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show(); - } - - private void onWakeLockRelease(int id, String name) { - if (id > 1) { - Log.d(TAG, "invalid pkg id"); - return; - } - int[] uids = new int[]{mUids[id]}; - String[] tags = new String[]{"release"}; - StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags, - StatsLog.WAKELOCK_STATE_CHANGED__TYPE__PARTIAL_WAKE_LOCK, name, - StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE); - StringBuilder sb = new StringBuilder(); - sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0) - .append(", ").append(name).append(", 0);"); - Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show(); - } - - public static class ReceiverIntentService extends IntentService { - public ReceiverIntentService() { - super("ReceiverIntentService"); - } - - /** - * The IntentService calls this method from the default worker thread with - * the intent that started the service. When this method returns, IntentService - * stops the service, as appropriate. - */ - @Override - protected void onHandleIntent(Intent intent) { - Log.i(TAG, "Received notification that we should call getData"); - } - } -} diff --git a/cmds/statsd/tools/loadtest/Android.bp b/cmds/statsd/tools/loadtest/Android.bp deleted file mode 100644 index bf87fc51dce1..000000000000 --- a/cmds/statsd/tools/loadtest/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2017 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. -// -// - -android_app { - name: "StatsdLoadtest", - platform_apis: true, - - srcs: ["src/**/*.java"], - - resource_dirs: ["res"], - static_libs: [ - "platformprotoslite", - "statsdprotolite", - ], - - certificate: "platform", - privileged: true, - dex_preopt: { - enabled: false, - }, - optimize: { - enabled: false, - }, -} diff --git a/cmds/statsd/tools/loadtest/AndroidManifest.xml b/cmds/statsd/tools/loadtest/AndroidManifest.xml deleted file mode 100644 index 2bf8ca95d846..000000000000 --- a/cmds/statsd/tools/loadtest/AndroidManifest.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.statsd.loadtest" - android:sharedUserId="android.uid.system" - android:versionCode="1" - android:versionName="1.0" > - - <uses-permission android:name="android.permission.DUMP" /> - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <application - android:allowBackup="true" - android:icon="@drawable/ic_launcher" - android:label="@string/app_name" > - <activity - android:name=".LoadtestActivity" - android:label="@string/app_name" - android:launchMode="singleTop" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - <receiver android:name=".LoadtestActivity$PusherAlarmReceiver" /> - <receiver android:name=".LoadtestActivity$StopperAlarmReceiver"/> - <receiver android:name=".PerfData$PerfAlarmReceiver"/> - </application> -</manifest> diff --git a/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 55621cc1074f..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 11ec2068be19..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 7c02b784aa5d..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 915d91441349..000000000000 --- a/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml b/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml deleted file mode 100644 index d6f804734385..000000000000 --- a/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml +++ /dev/null @@ -1,208 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, 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. -*/ ---> -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" > - - <LinearLayout - android:id="@+id/outside" - android:clickable="true" - android:focusable="true" - android:focusableInTouchMode="true" - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginRight="10dp" - android:layout_marginLeft="10dp" - android:orientation="vertical"> - <requestFocus /> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/replication_label" /> - <EditText - android:id="@+id/replication" - android:inputType="number" - android:layout_weight="1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:maxLength="4" - android:text="@integer/replication_default" - android:textSize="30dp"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/bucket_label" /> - <Spinner - android:id="@+id/bucket_spinner" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:prompt="@string/bucket_label"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/period_label" /> - <EditText - android:id="@+id/period" - android:inputType="number" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:maxLength="3" - android:text="@integer/period_default" - android:textSize="30dp"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/burst_label" /> - <EditText - android:id="@+id/burst" - android:inputType="number" - android:layout_weight="1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:maxLength="4" - android:text="@integer/burst_default" - android:textSize="30dp"/> - </LinearLayout> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal"> - <TextView - android:textSize="30dp" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/duration_label" /> - <EditText - android:id="@+id/duration" - android:inputType="number" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:maxLength="4" - android:text="@integer/duration_default" - android:textSize="30dp"/> - </LinearLayout> - <CheckBox - android:id="@+id/placebo" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/placebo" - android:checked="false" /> - - <LinearLayout - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <CheckBox - android:id="@+id/include_count" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/count" - android:checked="true"/> - <CheckBox - android:id="@+id/include_duration" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/duration" - android:checked="true"/> - <CheckBox - android:id="@+id/include_event" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/event" - android:checked="true"/> - <CheckBox - android:id="@+id/include_value" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/value" - android:checked="true"/> - <CheckBox - android:id="@+id/include_gauge" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/gauge" - android:checked="true"/> - </LinearLayout> - - <Space - android:layout_width="1dp" - android:layout_height="30dp"/> - - <Button - android:id="@+id/start_stop" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="#ffff0000" - android:text="@string/start" - android:textSize="50dp"/> - - <Space - android:layout_width="1dp" - android:layout_height="30dp"/> - - <Space - android:layout_width="1dp" - android:layout_height="30dp"/> - - <TextView - android:id="@+id/report_text" - android:gravity="center" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - </LinearLayout> - -</ScrollView> diff --git a/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml b/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml deleted file mode 100644 index b03da06f7a77..000000000000 --- a/cmds/statsd/tools/loadtest/res/layout/spinner_item.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textSize="30dp" - android:gravity="left" - android:padding="5dip" - /> diff --git a/cmds/statsd/tools/loadtest/res/raw/loadtest_config b/cmds/statsd/tools/loadtest/res/raw/loadtest_config Binary files differdeleted file mode 100755 index 24221908cbeb..000000000000 --- a/cmds/statsd/tools/loadtest/res/raw/loadtest_config +++ /dev/null diff --git a/cmds/statsd/tools/loadtest/res/values/integers.xml b/cmds/statsd/tools/loadtest/res/values/integers.xml deleted file mode 100644 index c2407d3b85f2..000000000000 --- a/cmds/statsd/tools/loadtest/res/values/integers.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<resources> - <integer name="burst_default">1</integer> - <integer name="period_default">2</integer> - <integer name="replication_default">1</integer> - <integer name="duration_default">240</integer> -</resources> diff --git a/cmds/statsd/tools/loadtest/res/values/strings.xml b/cmds/statsd/tools/loadtest/res/values/strings.xml deleted file mode 100644 index e8ae3f82a7e3..000000000000 --- a/cmds/statsd/tools/loadtest/res/values/strings.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<resources> - <string name="app_name">Statsd Loadtest</string> - <string name="bucket_label">bucket size (mins): </string> - <string name="burst_label">burst: </string> - <string name="bucket_default">FIVE_MINUTES</string> - <string name="placebo">placebo</string> - <string name="period_label">logging period (secs): </string> - <string name="replication_label">metric replication: </string> - <string name="duration_label">test duration (mins): </string> - <string name="start">  Start  </string> - <string name="stop">  Stop  </string> - <string name="count"> count </string> - <string name="duration"> duration </string> - <string name="event"> event </string> - <string name="value"> value </string> - <string name="gauge"> gauge </string> - -</resources> diff --git a/cmds/statsd/tools/loadtest/run_loadtest.sh b/cmds/statsd/tools/loadtest/run_loadtest.sh deleted file mode 100755 index 3c93a0613183..000000000000 --- a/cmds/statsd/tools/loadtest/run_loadtest.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/sh -# -# Script that measures statsd's PSS under an increasing number of metrics. - -# Globals. -pss="" -pid="" - -# Starts the loadtest. -start_loadtest() { - echo "Starting loadtest" - adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "start" -} - -# Stops the loadtest. -stop_loadtest() { - echo "Stopping loadtest" - adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "stop" -} - -# Sets the metrics replication. -# Arguments: -# $1: The replication factor. -set_replication() { - adb shell am start -n com.android.statsd.loadtest/.LoadtestActivity --es "type" "set_replication" --ei "replication" "${1}" - echo "Replication set to ${1}" -} - -# Reads statsd's pid and PSS. -update_pid_and_pss() { - # Command that reads the PSS for statsd. This also gives us its pid. - get_mem=$(adb shell dumpsys meminfo |grep statsd) - # Looks for statsd's pid. - regex="([0-9,]+)K: statsd \(pid ([0-9]+)\).*" - if [[ $get_mem =~ $regex ]]; then - pss=$(echo "${BASH_REMATCH[1]}" | tr -d , | sed 's/\.//g') - pid=$(echo "${BASH_REMATCH[2]}") - else - echo $cmd doesnt match $regex - fi -} - -# Kills statsd. -# Assumes the pid has been set. -kill_statsd() { - echo "Killing statsd (pid ${pid})" - adb shell kill -9 "${pid}" -} - -# Main loop. -main() { - start_time=$(date +%s) - values=() - stop_loadtest - - echo "" - echo "********************* NEW LOADTEST ************************" - update_pid_and_pss - for replication in 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 - do - echo "**** Starting test at replication ${replication} ****" - - # (1) Restart statsd. This will ensure its state is empty. - kill_statsd - sleep 3 # wait a bit for it to restart - update_pid_and_pss - echo "Before the test, statsd's PSS is ${pss}" - - # (2) Set the replication. - set_replication "${replication}" - sleep 1 # wait a bit - - # (3) Start the loadtest. - start_loadtest - - # (4) Wait several seconds, then read the PSS. - sleep 100 && update_pid_and_pss - echo "During the test, statsd's PSS is ${pss}" - values+=(${pss}) - - echo "Values: ${values[@]}" - - # (5) Stop loadtest. - stop_loadtest - sleep 2 - - echo "" - done - - end_time=$(date +%s) - echo "Completed loadtest in $((${end_time} - ${start_time})) seconds." - - values_as_str=$(IFS=$'\n'; echo "${values[*]}") - echo "The PSS values are:" - echo "${values_as_str}" - echo "" -} - -main diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java deleted file mode 100644 index bab0c1e3f540..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryDataRecorder.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.content.Context; -import android.util.Log; -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import java.text.ParseException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class BatteryDataRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.BatteryDataRecorder"; - private static final String DUMP_FILENAME = TAG + "_dump.tmp"; - - public BatteryDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs, - int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - } - - @Override - public void startRecording(Context context) { - // Reset batterystats. - runDumpsysStats(context, DUMP_FILENAME, "batterystats", "--reset"); - } - - @Override - public void onAlarm(Context context) { - // Nothing to do as for battery, the whole data is in the final dumpsys call. - } - - @Override - public void stopRecording(Context context) { - StringBuilder sb = new StringBuilder(); - // Don't use --checkin. - runDumpsysStats(context, DUMP_FILENAME, "batterystats"); - readDumpData(context, DUMP_FILENAME, new BatteryStatsParser(), sb); - writeData(context, "battery_", "time,battery_level", sb); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java deleted file mode 100644 index 203d97acefd8..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.util.Log; -import java.text.ParseException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class BatteryStatsParser implements PerfParser { - - private static final Pattern LINE_PATTERN = - Pattern.compile("\\s*\\+*(\\S*)\\s\\(\\d+\\)\\s(\\d\\d\\d)\\s.*"); - private static final Pattern TIME_PATTERN = - Pattern.compile("(\\d+)?(h)?(\\d+)?(m)?(\\d+)?(s)?(\\d+)?(ms)?"); - private static final String TAG = "loadtest.BatteryStatsParser"; - - private boolean mHistoryStarted; - private boolean mHistoryEnded; - - public BatteryStatsParser() { - } - - @Override - @Nullable - public String parseLine(String line) { - if (mHistoryEnded) { - return null; - } - if (!mHistoryStarted) { - if (line.contains("Battery History")) { - mHistoryStarted = true; - } - return null; - } - if (line.isEmpty()) { - mHistoryEnded = true; - return null; - } - Matcher lineMatcher = LINE_PATTERN.matcher(line); - if (lineMatcher.find() && lineMatcher.group(1) != null && lineMatcher.group(2) != null) { - if (lineMatcher.group(1).equals("0")) { - return "0," + lineMatcher.group(2) + "\n"; - } else { - Matcher timeMatcher = TIME_PATTERN.matcher(lineMatcher.group(1)); - if (timeMatcher.find()) { - Long time = getTime(lineMatcher.group(1)); - if (time != null) { - return time + "," + lineMatcher.group(2) + "\n"; - } else { - return null; // bad time - } - } else { - return null; // bad or no time - } - } - } - return null; - } - - @Nullable - private Long getTime(String group) { - if ("0".equals(group)) { - return 0L; - } - Matcher timeMatcher = TIME_PATTERN.matcher(group); - if (!timeMatcher.find()) { - return null; - } - - // Get rid of "ms". - String[] matches = group.split("ms", -1); - if (matches.length > 1) { - group = matches[0]; - } - - long time = 0L; - matches = group.split("h"); - if (matches.length > 1) { - time += Long.parseLong(matches[0]) * 60 * 60 * 1000; // hours - group = matches[1]; - } - matches = group.split("m"); - if (matches.length > 1) { - time += Long.parseLong(matches[0]) * 60 * 1000; // minutes - group = matches[1]; - } - matches = group.split("s"); - if (matches.length > 1) { - time += Long.parseLong(matches[0]) * 1000; // seconds - group = matches[1]; - } - - if (!group.isEmpty()) { - time += Long.parseLong(group); // milliseconds - } - return time; - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java deleted file mode 100644 index 2e0161be8096..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import android.content.res.Resources; -import android.util.Log; - -import com.android.internal.os.StatsdConfigProto.Predicate; -import com.android.internal.os.StatsdConfigProto.CountMetric; -import com.android.internal.os.StatsdConfigProto.DurationMetric; -import com.android.internal.os.StatsdConfigProto.MetricConditionLink; -import com.android.internal.os.StatsdConfigProto.EventMetric; -import com.android.internal.os.StatsdConfigProto.GaugeMetric; -import com.android.internal.os.StatsdConfigProto.ValueMetric; -import com.android.internal.os.StatsdConfigProto.FieldValueMatcher; -import com.android.internal.os.StatsdConfigProto.AtomMatcher; -import com.android.internal.os.StatsdConfigProto.SimplePredicate; -import com.android.internal.os.StatsdConfigProto.StatsdConfig; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -import java.io.InputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * Creates StatsdConfig protos for loadtesting. - */ -public class ConfigFactory { - public static class ConfigMetadata { - public final byte[] bytes; - public final int numMetrics; - - public ConfigMetadata(byte[] bytes, int numMetrics) { - this.bytes = bytes; - this.numMetrics = numMetrics; - } - } - - public static final long CONFIG_ID = 123456789; - - private static final String TAG = "loadtest.ConfigFactory"; - - private final StatsdConfig mTemplate; - - public ConfigFactory(Context context) { - // Read the config template from the resoures. - Resources res = context.getResources(); - byte[] template = null; - StatsdConfig templateProto = null; - try { - InputStream inputStream = res.openRawResource(R.raw.loadtest_config); - template = new byte[inputStream.available()]; - inputStream.read(template); - templateProto = StatsdConfig.parseFrom(template); - } catch (IOException e) { - Log.e(TAG, "Unable to read or parse loadtest config template. Using an empty config."); - } - mTemplate = templateProto == null ? StatsdConfig.newBuilder().build() : templateProto; - - Log.d(TAG, "Loadtest template config: " + mTemplate); - } - - /** - * Generates a config. - * - * All configs are based on the same template. - * That template is designed to make the most use of the set of atoms that {@code SequencePusher} - * pushes, and to exercise as many of the metrics features as possible. - * Furthermore, by passing a replication factor to this method, one can artificially inflate - * the number of metrics in the config. One can also adjust the bucket size for aggregate - * metrics. - * - * @param replication The number of times each metric is replicated in the config. - * If the config template has n metrics, the generated config will have n * replication - * ones - * @param bucketMillis The bucket size, in milliseconds, for aggregate metrics - * @param placebo If true, only return an empty config - * @return The serialized config and the number of metrics. - */ - public ConfigMetadata getConfig(int replication, TimeUnit bucket, boolean placebo, - boolean includeCount, boolean includeDuration, boolean includeEvent, - boolean includeValue, boolean includeGauge) { - StatsdConfig.Builder config = StatsdConfig.newBuilder() - .setId(CONFIG_ID); - if (placebo) { - replication = 0; // Config will be empty, aside from a name. - } - int numMetrics = 0; - for (int i = 0; i < replication; i++) { - // metrics - if (includeEvent) { - for (EventMetric metric : mTemplate.getEventMetricList()) { - addEventMetric(metric, i, config); - numMetrics++; - } - } - if (includeCount) { - for (CountMetric metric : mTemplate.getCountMetricList()) { - addCountMetric(metric, i, bucket, config); - numMetrics++; - } - } - if (includeDuration) { - for (DurationMetric metric : mTemplate.getDurationMetricList()) { - addDurationMetric(metric, i, bucket, config); - numMetrics++; - } - } - if (includeGauge) { - for (GaugeMetric metric : mTemplate.getGaugeMetricList()) { - addGaugeMetric(metric, i, bucket, config); - numMetrics++; - } - } - if (includeValue) { - for (ValueMetric metric : mTemplate.getValueMetricList()) { - addValueMetric(metric, i, bucket, config); - numMetrics++; - } - } - // predicates - for (Predicate predicate : mTemplate.getPredicateList()) { - addPredicate(predicate, i, config); - } - // matchers - for (AtomMatcher matcher : mTemplate.getAtomMatcherList()) { - addMatcher(matcher, i, config); - } - } - - Log.d(TAG, "Loadtest config is : " + config.build()); - Log.d(TAG, "Generated config has " + numMetrics + " metrics"); - - return new ConfigMetadata(config.build().toByteArray(), numMetrics); - } - - /** - * Creates {@link MetricConditionLink}s that are identical to the one passed to this method, - * except that the names are appended with the provided suffix. - */ - private List<MetricConditionLink> getLinks( - List<MetricConditionLink> links, int suffix) { - List<MetricConditionLink> newLinks = new ArrayList(); - for (MetricConditionLink link : links) { - newLinks.add(link.toBuilder() - .setCondition(link.getCondition() + suffix) - .build()); - } - return newLinks; - } - - /** - * Creates an {@link EventMetric} based on the template. Makes sure that all names are appended - * with the provided suffix. Then adds that metric to the config. - */ - private void addEventMetric(EventMetric template, int suffix, StatsdConfig.Builder config) { - EventMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - config.addEventMetric(metric); - } - - /** - * Creates a {@link CountMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addCountMetric(CountMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - CountMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addCountMetric(metric); - } - - /** - * Creates a {@link DurationMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addDurationMetric(DurationMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - DurationMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addDurationMetric(metric); - } - - /** - * Creates a {@link GaugeMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addGaugeMetric(GaugeMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - GaugeMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addGaugeMetric(metric); - } - - /** - * Creates a {@link ValueMetric} based on the template. Makes sure that all names are appended - * with the provided suffix, and overrides the bucket size. Then adds that metric to the config. - */ - private void addValueMetric(ValueMetric template, int suffix, TimeUnit bucket, - StatsdConfig.Builder config) { - ValueMetric.Builder metric = template.toBuilder() - .setId(template.getId() + suffix) - .setWhat(template.getWhat() + suffix); - if (template.hasCondition()) { - metric.setCondition(template.getCondition() + suffix); - } - if (template.getLinksCount() > 0) { - List<MetricConditionLink> links = getLinks(template.getLinksList(), suffix); - metric.clearLinks(); - metric.addAllLinks(links); - } - metric.setBucket(bucket); - config.addValueMetric(metric); - } - - /** - * Creates a {@link Predicate} based on the template. Makes sure that all names - * are appended with the provided suffix. Then adds that predicate to the config. - */ - private void addPredicate(Predicate template, int suffix, StatsdConfig.Builder config) { - Predicate.Builder predicate = template.toBuilder() - .setId(template.getId() + suffix); - if (template.hasCombination()) { - Predicate.Combination.Builder cb = template.getCombination().toBuilder() - .clearPredicate(); - for (long child : template.getCombination().getPredicateList()) { - cb.addPredicate(child + suffix); - } - predicate.setCombination(cb.build()); - } - if (template.hasSimplePredicate()) { - SimplePredicate.Builder sc = template.getSimplePredicate().toBuilder() - .setStart(template.getSimplePredicate().getStart() + suffix) - .setStop(template.getSimplePredicate().getStop() + suffix); - if (template.getSimplePredicate().hasStopAll()) { - sc.setStopAll(template.getSimplePredicate().getStopAll() + suffix); - } - predicate.setSimplePredicate(sc.build()); - } - config.addPredicate(predicate); - } - - /** - * Creates a {@link AtomMatcher} based on the template. Makes sure that all names - * are appended with the provided suffix. Then adds that matcher to the config. - */ - private void addMatcher(AtomMatcher template, int suffix, StatsdConfig.Builder config) { - AtomMatcher.Builder matcher = template.toBuilder() - .setId(template.getId() + suffix); - if (template.hasCombination()) { - AtomMatcher.Combination.Builder cb = template.getCombination().toBuilder() - .clearMatcher(); - for (long child : template.getCombination().getMatcherList()) { - cb.addMatcher(child + suffix); - } - matcher.setCombination(cb); - } - config.addAtomMatcher(matcher); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java deleted file mode 100644 index d55f3f31fd9f..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.text.format.DateFormat; - -import com.android.os.StatsLog; - -import java.util.List; - -public class DisplayProtoUtils { - private static final int MAX_NUM_METRICS_TO_DISPLAY = 10; - - public static void displayLogReport(StringBuilder sb, StatsLog.ConfigMetricsReportList reports) { - sb.append("******************** Report ********************\n"); - if (reports.hasConfigKey()) { - sb.append("ConfigKey: "); - com.android.os.StatsLog.ConfigMetricsReportList.ConfigKey key = reports.getConfigKey(); - sb.append("\tuid: ").append(key.getUid()).append(" id: ").append(key.getId()) - .append("\n"); - } - - int numMetrics = 0; - for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) { - sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n"); - sb.append("Last report time:").append(getDateStr(report.getLastReportElapsedNanos())). - append("\n"); - sb.append("Current report time:").append(getDateStr(report.getCurrentReportElapsedNanos())). - append("\n"); - for (StatsLog.StatsLogReport log : report.getMetricsList()) { - numMetrics++; - if (numMetrics > MAX_NUM_METRICS_TO_DISPLAY) { - sb.append("... output truncated\n"); - sb.append("************************************************"); - return; - } - sb.append("\n"); - sb.append("metric id: ").append(log.getMetricId()).append("\n"); - - switch (log.getDataCase()) { - case DURATION_METRICS: - sb.append("Duration metric data\n"); - displayDurationMetricData(sb, log); - break; - case EVENT_METRICS: - sb.append("Event metric data\n"); - displayEventMetricData(sb, log); - break; - case COUNT_METRICS: - sb.append("Count metric data\n"); - displayCountMetricData(sb, log); - break; - case GAUGE_METRICS: - sb.append("Gauge metric data\n"); - displayGaugeMetricData(sb, log); - break; - case VALUE_METRICS: - sb.append("Value metric data\n"); - displayValueMetricData(sb, log); - break; - case DATA_NOT_SET: - sb.append("No metric data\n"); - break; - } - } - } - sb.append("************************************************"); - } - - public static String getDateStr(long nanoSec) { - return DateFormat.format("dd/MM hh:mm:ss", nanoSec/1000000).toString(); - } - - private static void displayDimension(StringBuilder sb, StatsLog.DimensionsValue dimensionValue) { - sb.append(dimensionValue.getField()).append(":"); - if (dimensionValue.hasValueBool()) { - sb.append(dimensionValue.getValueBool()); - } else if (dimensionValue.hasValueFloat()) { - sb.append(dimensionValue.getValueFloat()); - } else if (dimensionValue.hasValueInt()) { - sb.append(dimensionValue.getValueInt()); - } else if (dimensionValue.hasValueStr()) { - sb.append(dimensionValue.getValueStr()); - } else if (dimensionValue.hasValueTuple()) { - sb.append("{"); - for (StatsLog.DimensionsValue child : - dimensionValue.getValueTuple().getDimensionsValueList()) { - displayDimension(sb, child); - } - sb.append("}"); - } - sb.append(" "); - } - - public static void displayDurationMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - StatsLog.StatsLogReport.DurationMetricDataWrapper durationMetricDataWrapper - = log.getDurationMetrics(); - sb.append("Dimension size: ").append(durationMetricDataWrapper.getDataCount()).append("\n"); - for (StatsLog.DurationMetricData duration : durationMetricDataWrapper.getDataList()) { - sb.append("dimension_in_what: "); - displayDimension(sb, duration.getDimensionsInWhat()); - sb.append("\n"); - if (duration.hasDimensionsInCondition()) { - sb.append("dimension_in_condition: "); - displayDimension(sb, duration.getDimensionsInCondition()); - sb.append("\n"); - } - - for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") - .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") - .append(info.getDurationNanos()).append(" ns\n"); - } - } - } - - public static void displayEventMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Contains ").append(log.getEventMetrics().getDataCount()).append(" events\n"); - StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper = - log.getEventMetrics(); - for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) { - sb.append(getDateStr(event.getElapsedTimestampNanos())).append(": "); - sb.append(event.getAtom().getPushedCase().toString()).append("\n"); - } - } - - public static void displayCountMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - StatsLog.StatsLogReport.CountMetricDataWrapper countMetricDataWrapper - = log.getCountMetrics(); - sb.append("Dimension size: ").append(countMetricDataWrapper.getDataCount()).append("\n"); - for (StatsLog.CountMetricData count : countMetricDataWrapper.getDataList()) { - sb.append("dimension_in_what: "); - displayDimension(sb, count.getDimensionsInWhat()); - sb.append("\n"); - if (count.hasDimensionsInCondition()) { - sb.append("dimension_in_condition: "); - displayDimension(sb, count.getDimensionsInCondition()); - sb.append("\n"); - } - - for (StatsLog.CountBucketInfo info : count.getBucketInfoList()) { - sb.append("\t[").append(getDateStr(info.getStartBucketElapsedNanos())).append("-") - .append(getDateStr(info.getEndBucketElapsedNanos())).append("] -> ") - .append(info.getCount()).append("\n"); - } - } - } - - public static void displayGaugeMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Display me!"); - } - - public static void displayValueMetricData(StringBuilder sb, StatsLog.StatsLogReport log) { - sb.append("Display me!"); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java deleted file mode 100644 index 769f78c726e8..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.app.Activity; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.app.StatsManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.os.Handler; -import android.os.IStatsManager; -import android.os.PowerManager; -import android.os.PowerManager.WakeLock; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.util.StatsLog; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.view.MotionEvent; -import android.view.View.OnFocusChangeListener; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -import com.android.os.StatsLog.ConfigMetricsReport; -import com.android.os.StatsLog.ConfigMetricsReportList; -import com.android.os.StatsLog.StatsdStatsReport; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Runs a load test for statsd. - * How it works: - * <ul> - * <li> Sets up and pushes a custom config with metrics that exercise a large swath of code paths. - * <li> Periodically logs certain atoms into logd. - * <li> Impact on battery can be printed to logcat, or a bug report can be filed and analyzed - * in battery Historian. - * </ul> - * The load depends on how demanding the config is, as well as how frequently atoms are pushsed - * to logd. Those are all controlled by 4 adjustable parameters: - * <ul> - * <li> The 'replication' parameter artificially multiplies the number of metrics in the config. - * <li> The bucket size controls the time-bucketing the aggregate metrics. - * <li> The period parameter controls how frequently atoms are pushed to logd. - * <li> The 'burst' parameter controls how many atoms are pushed at the same time (per period). - * </ul> - */ -public class LoadtestActivity extends Activity implements AdapterView.OnItemSelectedListener { - - private static final String TAG = "loadtest.LoadtestActivity"; - public static final String TYPE = "type"; - private static final String PUSH_ALARM = "push_alarm"; - public static final String PERF_ALARM = "perf_alarm"; - private static final String SET_REPLICATION = "set_replication"; - private static final String REPLICATION = "replication"; - private static final String START = "start"; - private static final String STOP = "stop"; - private static final Map<String, TimeUnit> TIME_UNIT_MAP = initializeTimeUnitMap(); - private static final List<String> TIME_UNIT_LABELS = initializeTimeUnitLabels(); - - public final static class PusherAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Intent activityIntent = new Intent(context, LoadtestActivity.class); - activityIntent.putExtra(TYPE, PUSH_ALARM); - context.startActivity(activityIntent); - } - } - - public final static class StopperAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Intent activityIntent = new Intent(context, LoadtestActivity.class); - activityIntent.putExtra(TYPE, STOP); - context.startActivity(activityIntent); - } - } - - private static Map<String, TimeUnit> initializeTimeUnitMap() { - Map<String, TimeUnit> labels = new HashMap(); - labels.put("1m", TimeUnit.ONE_MINUTE); - labels.put("5m", TimeUnit.FIVE_MINUTES); - labels.put("10m", TimeUnit.TEN_MINUTES); - labels.put("30m", TimeUnit.THIRTY_MINUTES); - labels.put("1h", TimeUnit.ONE_HOUR); - labels.put("3h", TimeUnit.THREE_HOURS); - labels.put("6h", TimeUnit.SIX_HOURS); - labels.put("12h", TimeUnit.TWELVE_HOURS); - labels.put("1d", TimeUnit.ONE_DAY); - labels.put("1s", TimeUnit.CTS); - return labels; - } - - private static List<String> initializeTimeUnitLabels() { - List<String> labels = new ArrayList(); - labels.add("1s"); - labels.add("1m"); - labels.add("5m"); - labels.add("10m"); - labels.add("30m"); - labels.add("1h"); - labels.add("3h"); - labels.add("6h"); - labels.add("12h"); - labels.add("1d"); - return labels; - } - - private AlarmManager mAlarmMgr; - - /** - * Used to periodically log atoms to logd. - */ - private PendingIntent mPushPendingIntent; - - /** - * Used to end the loadtest. - */ - private PendingIntent mStopPendingIntent; - - private Button mStartStop; - private EditText mReplicationText; - private Spinner mBucketSpinner; - private EditText mPeriodText; - private EditText mBurstText; - private EditText mDurationText; - private TextView mReportText; - private CheckBox mPlaceboCheckBox; - private CheckBox mCountMetricCheckBox; - private CheckBox mDurationMetricCheckBox; - private CheckBox mEventMetricCheckBox; - private CheckBox mValueMetricCheckBox; - private CheckBox mGaugeMetricCheckBox; - - /** - * When the load test started. - */ - private long mStartedTimeMillis; - - /** - * For measuring perf data. - */ - private PerfData mPerfData; - - /** - * For communicating with statsd. - */ - private StatsManager mStatsManager; - - private PowerManager mPowerManager; - private WakeLock mWakeLock; - - /** - * If true, we only measure the effect of the loadtest infrastructure. No atom are pushed and - * the configuration is empty. - */ - private boolean mPlacebo; - - /** - * Whether to include CountMetric in the config. - */ - private boolean mIncludeCountMetric; - - /** - * Whether to include DurationMetric in the config. - */ - private boolean mIncludeDurationMetric; - - /** - * Whether to include EventMetric in the config. - */ - private boolean mIncludeEventMetric; - - /** - * Whether to include ValueMetric in the config. - */ - private boolean mIncludeValueMetric; - - /** - * Whether to include GaugeMetric in the config. - */ - private boolean mIncludeGaugeMetric; - - /** - * The burst size. - */ - private int mBurst; - - /** - * The metrics replication. - */ - private int mReplication; - - /** - * The period, in seconds, at which batches of atoms are pushed. - */ - private long mPeriodSecs; - - /** - * The bucket size, in minutes, for aggregate metrics. - */ - private TimeUnit mBucket; - - /** - * The duration, in minutes, of the loadtest. - */ - private long mDurationMins; - - /** - * Whether the loadtest has started. - */ - private boolean mStarted = false; - - /** - * Orchestrates the logging of pushed events into logd. - */ - private SequencePusher mPusher; - - /** - * Generates statsd configs. - */ - private ConfigFactory mFactory; - - /** - * For intra-minute periods. - */ - private final Handler mHandler = new Handler(); - - /** - * Number of metrics in the current config. - */ - private int mNumMetrics; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Log.d(TAG, "Starting loadtest Activity"); - - setContentView(R.layout.activity_loadtest); - mReportText = (TextView) findViewById(R.id.report_text); - initBurst(); - initReplication(); - initBucket(); - initPeriod(); - initDuration(); - initPlacebo(); - initMetricWhitelist(); - - // Hide the keyboard outside edit texts. - findViewById(R.id.outside).setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - InputMethodManager imm = - (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - if (getCurrentFocus() != null) { - imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); - } - return true; - } - }); - - mStartStop = findViewById(R.id.start_stop); - mStartStop.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (mStarted) { - stopLoadtest(); - } else { - startLoadtest(); - } - } - }); - - mAlarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE); - mStatsManager = (StatsManager) getSystemService("stats"); - mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); - mFactory = new ConfigFactory(this); - stopLoadtest(); - mReportText.setText(""); - } - - @Override - public void onNewIntent(Intent intent) { - String type = intent.getStringExtra(TYPE); - if (type == null) { - return; - } - switch (type) { - case PERF_ALARM: - onPerfAlarm(); - break; - case PUSH_ALARM: - onAlarm(); - break; - case SET_REPLICATION: - if (intent.hasExtra(REPLICATION)) { - setReplication(intent.getIntExtra(REPLICATION, 0)); - } - break; - case START: - startLoadtest(); - break; - case STOP: - stopLoadtest(); - break; - default: - throw new IllegalArgumentException("Unknown type: " + type); - } - } - - @Override - public void onDestroy() { - Log.d(TAG, "Destroying"); - mPerfData.onDestroy(); - stopLoadtest(); - clearConfigs(); - super.onDestroy(); - } - - @Nullable - public StatsdStatsReport getMetadata() { - if (!statsdRunning()) { - return null; - } - if (mStatsManager != null) { - byte[] data; - try { - data = mStatsManager.getStatsMetadata(); - } catch (StatsManager.StatsUnavailableException e) { - Log.e(TAG, "Failed to get data from statsd", e); - return null; - } - if (data != null) { - StatsdStatsReport report = null; - boolean good = false; - try { - return StatsdStatsReport.parseFrom(data); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - Log.d(TAG, "Bad StatsdStatsReport"); - } - } - } - return null; - } - - @Nullable - public List<ConfigMetricsReport> getData() { - if (!statsdRunning()) { - return null; - } - if (mStatsManager != null) { - byte[] data; - try { - data = mStatsManager.getReports(ConfigFactory.CONFIG_ID); - } catch (StatsManager.StatsUnavailableException e) { - Log.e(TAG, "Failed to get data from statsd", e); - return null; - } - if (data != null) { - ConfigMetricsReportList reports = null; - try { - reports = ConfigMetricsReportList.parseFrom(data); - Log.d(TAG, "Num reports: " + reports.getReportsCount()); - StringBuilder sb = new StringBuilder(); - DisplayProtoUtils.displayLogReport(sb, reports); - Log.d(TAG, sb.toString()); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - Log.d(TAG, "Invalid data"); - } - if (reports != null) { - return reports.getReportsList(); - } - } - } - return null; - } - - @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - String item = parent.getItemAtPosition(position).toString(); - - mBucket = TIME_UNIT_MAP.get(item); - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - // Another interface callback - } - - private void onPerfAlarm() { - if (mPerfData != null) { - mPerfData.onAlarm(this); - } - // Piggy-back on that alarm to show the elapsed time. - long elapsedTimeMins = (long) Math.floor( - (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000); - mReportText.setText("Loadtest in progress.\n" - + "num metrics =" + mNumMetrics - + "\nElapsed time = " + elapsedTimeMins + " min(s)"); - } - - private void onAlarm() { - Log.d(TAG, "ON ALARM"); - - // Set the next task. - scheduleNext(); - - // Do the work. - mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "StatsdLoadTest"); - mWakeLock.acquire(); - if (mPusher != null) { - mPusher.next(); - } - mWakeLock.release(); - mWakeLock = null; - } - - /** - * Schedules the next cycle of pushing atoms into logd. - */ - private void scheduleNext() { - Intent intent = new Intent(this, PusherAlarmReceiver.class); - intent.putExtra(TYPE, PUSH_ALARM); - mPushPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); - long nextTime = SystemClock.elapsedRealtime() + mPeriodSecs * 1000; - mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mPushPendingIntent); - } - - private synchronized void startLoadtest() { - if (mStarted) { - return; - } - - // Clean up the state. - stopLoadtest(); - - // Prepare to push a sequence of atoms to logd. - mPusher = new SequencePusher(mBurst, mPlacebo); - - // Create a config and push it to statsd. - if (!setConfig(mFactory.getConfig(mReplication, mBucket, mPlacebo, - mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric, - mIncludeValueMetric, mIncludeGaugeMetric))) { - return; - } - - // Remember to stop in the future. - Intent intent = new Intent(this, StopperAlarmReceiver.class); - intent.putExtra(TYPE, STOP); - mStopPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); - long nextTime = SystemClock.elapsedRealtime() + mDurationMins * 60 * 1000; - mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mStopPendingIntent); - - // Log atoms. - scheduleNext(); - - // Start tracking performance. - mPerfData = new PerfData(this, mPlacebo, mReplication, mBucket, mPeriodSecs, mBurst, - mIncludeCountMetric, mIncludeDurationMetric, mIncludeEventMetric, mIncludeValueMetric, - mIncludeGaugeMetric); - mPerfData.startRecording(this); - - mReportText.setText("Loadtest in progress.\nnum metrics =" + mNumMetrics); - mStartedTimeMillis = SystemClock.elapsedRealtime(); - - updateStarted(true); - } - - private synchronized void stopLoadtest() { - if (mPushPendingIntent != null) { - Log.d(TAG, "Canceling pre-existing push alarm"); - mAlarmMgr.cancel(mPushPendingIntent); - mPushPendingIntent = null; - } - if (mStopPendingIntent != null) { - Log.d(TAG, "Canceling pre-existing stop alarm"); - mAlarmMgr.cancel(mStopPendingIntent); - mStopPendingIntent = null; - } - if (mWakeLock != null) { - mWakeLock.release(); - mWakeLock = null; - } - if (mPerfData != null) { - mPerfData.stopRecording(this); - mPerfData.onDestroy(); - mPerfData = null; - } - - // Obtain the latest data and display it. - getData(); - - long elapsedTimeMins = (long) Math.floor( - (SystemClock.elapsedRealtime() - mStartedTimeMillis) / 60 / 1000); - mReportText.setText("Loadtest ended. Elapsed time = " + elapsedTimeMins + " min(s)"); - clearConfigs(); - updateStarted(false); - } - - private synchronized void updateStarted(boolean started) { - mStarted = started; - mStartStop.setBackgroundColor(started ? - Color.parseColor("#FFFF0000") : Color.parseColor("#FF00FF00")); - mStartStop.setText(started ? getString(R.string.stop) : getString(R.string.start)); - updateControlsEnabled(); - } - - private void updateControlsEnabled() { - mBurstText.setEnabled(!mPlacebo && !mStarted); - mReplicationText.setEnabled(!mPlacebo && !mStarted); - mPeriodText.setEnabled(!mStarted); - mBucketSpinner.setEnabled(!mPlacebo && !mStarted); - mDurationText.setEnabled(!mStarted); - mPlaceboCheckBox.setEnabled(!mStarted); - - boolean enabled = !mStarted && !mPlaceboCheckBox.isChecked(); - mCountMetricCheckBox.setEnabled(enabled); - mDurationMetricCheckBox.setEnabled(enabled); - mEventMetricCheckBox.setEnabled(enabled); - mValueMetricCheckBox.setEnabled(enabled); - mGaugeMetricCheckBox.setEnabled(enabled); - } - - private boolean statsdRunning() { - if (IStatsManager.Stub.asInterface(ServiceManager.getService("stats")) == null) { - Log.d(TAG, "Statsd not running"); - Toast.makeText(LoadtestActivity.this, "Statsd NOT running!", Toast.LENGTH_LONG).show(); - return false; - } - return true; - } - - private int sanitizeInt(int val, int min, int max) { - if (val > max) { - val = max; - } else if (val < min) { - val = min; - } - return val; - } - - private void clearConfigs() { - // TODO: Clear all configs instead of specific ones. - if (mStatsManager != null) { - if (mStarted) { - try { - mStatsManager.removeConfig(ConfigFactory.CONFIG_ID); - Log.d(TAG, "Removed loadtest statsd configs."); - } catch (StatsManager.StatsUnavailableException e) { - Log.e(TAG, "Failed to remove loadtest configs.", e); - } - } - } - } - - private boolean setConfig(ConfigFactory.ConfigMetadata configData) { - if (mStatsManager != null) { - try { - mStatsManager.addConfig(ConfigFactory.CONFIG_ID, configData.bytes); - mNumMetrics = configData.numMetrics; - Log.d(TAG, "Config pushed to statsd"); - return true; - } catch (StatsManager.StatsUnavailableException | IllegalArgumentException e) { - Log.e(TAG, "Failed to push config to statsd", e); - } - } - return false; - } - - private synchronized void setReplication(int replication) { - if (mStarted) { - return; - } - mReplicationText.setText("" + replication); - } - - private synchronized void setPeriodSecs(long periodSecs) { - mPeriodSecs = periodSecs; - } - - private synchronized void setBurst(int burst) { - mBurst = burst; - } - - private synchronized void setDurationMins(long durationMins) { - mDurationMins = durationMins; - } - - - private void handleFocus(EditText editText) { - /* - editText.setOnFocusChangeListener(new OnFocusChangeListener() { - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (!hasFocus && editText.getText().toString().isEmpty()) { - editText.setText("-1", TextView.BufferType.EDITABLE); - } - } - }); - */ - } - - private void initBurst() { - mBurst = getResources().getInteger(R.integer.burst_default); - mBurstText = (EditText) findViewById(R.id.burst); - mBurstText.addTextChangedListener(new NumericalWatcher(mBurstText, 0, 1000) { - @Override - public void onNewValue(int newValue) { - setBurst(newValue); - } - }); - handleFocus(mBurstText); - } - - private void initReplication() { - mReplication = getResources().getInteger(R.integer.replication_default); - mReplicationText = (EditText) findViewById(R.id.replication); - mReplicationText.addTextChangedListener(new NumericalWatcher(mReplicationText, 1, 4096) { - @Override - public void onNewValue(int newValue) { - mReplication = newValue; - } - }); - handleFocus(mReplicationText); - } - - private void initBucket() { - String defaultValue = getResources().getString(R.string.bucket_default); - mBucket = TimeUnit.valueOf(defaultValue); - mBucketSpinner = (Spinner) findViewById(R.id.bucket_spinner); - - ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>( - this, R.layout.spinner_item, TIME_UNIT_LABELS); - - mBucketSpinner.setAdapter(dataAdapter); - mBucketSpinner.setOnItemSelectedListener(this); - - for (String label : TIME_UNIT_MAP.keySet()) { - if (defaultValue.equals(TIME_UNIT_MAP.get(label).toString())) { - mBucketSpinner.setSelection(dataAdapter.getPosition(label)); - } - } - } - - private void initPeriod() { - mPeriodSecs = getResources().getInteger(R.integer.period_default); - mPeriodText = (EditText) findViewById(R.id.period); - mPeriodText.addTextChangedListener(new NumericalWatcher(mPeriodText, 1, 60) { - @Override - public void onNewValue(int newValue) { - setPeriodSecs(newValue); - } - }); - handleFocus(mPeriodText); - } - - private void initDuration() { - mDurationMins = getResources().getInteger(R.integer.duration_default); - mDurationText = (EditText) findViewById(R.id.duration); - mDurationText.addTextChangedListener(new NumericalWatcher(mDurationText, 1, 24 * 60) { - @Override - public void onNewValue(int newValue) { - setDurationMins(newValue); - } - }); - handleFocus(mDurationText); - } - - private void initPlacebo() { - mPlaceboCheckBox = findViewById(R.id.placebo); - mPlacebo = false; - mPlaceboCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mPlacebo = mPlaceboCheckBox.isChecked(); - updateControlsEnabled(); - } - }); - } - - private void initMetricWhitelist() { - mCountMetricCheckBox = findViewById(R.id.include_count); - mCountMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeCountMetric = mCountMetricCheckBox.isChecked(); - } - }); - mDurationMetricCheckBox = findViewById(R.id.include_duration); - mDurationMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeDurationMetric = mDurationMetricCheckBox.isChecked(); - } - }); - mEventMetricCheckBox = findViewById(R.id.include_event); - mEventMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeEventMetric = mEventMetricCheckBox.isChecked(); - } - }); - mValueMetricCheckBox = findViewById(R.id.include_value); - mValueMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeValueMetric = mValueMetricCheckBox.isChecked(); - } - }); - mGaugeMetricCheckBox = findViewById(R.id.include_gauge); - mGaugeMetricCheckBox.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - mIncludeGaugeMetric = mGaugeMetricCheckBox.isChecked(); - } - }); - - mIncludeCountMetric = mCountMetricCheckBox.isChecked(); - mIncludeDurationMetric = mDurationMetricCheckBox.isChecked(); - mIncludeEventMetric = mEventMetricCheckBox.isChecked(); - mIncludeValueMetric = mValueMetricCheckBox.isChecked(); - mIncludeGaugeMetric = mGaugeMetricCheckBox.isChecked(); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemInfoParser.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemInfoParser.java deleted file mode 100644 index 01eebf2ad1cf..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemInfoParser.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.os.SystemClock; -import android.util.Log; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** Parses PSS info from dumpsys meminfo */ -public class MemInfoParser implements PerfParser { - - private static final Pattern LINE_PATTERN = - Pattern.compile("\\s*(\\d*,*\\d*)K:\\s(\\S*)\\s\\.*"); - private static final String PSS_BY_PROCESS = "Total PSS by process:"; - private static final String TAG = "loadtest.MemInfoParser"; - - private boolean mPssStarted; - private boolean mPssEnded; - private final long mStartTimeMillis; - - public MemInfoParser(long startTimeMillis) { - mStartTimeMillis = startTimeMillis; - } - - @Override - @Nullable - public String parseLine(String line) { - if (mPssEnded) { - return null; - } - if (!mPssStarted) { - if (line.contains(PSS_BY_PROCESS)) { - mPssStarted = true; - } - return null; - } - if (line.isEmpty()) { - mPssEnded = true; - return null; - } - Matcher lineMatcher = LINE_PATTERN.matcher(line); - if (lineMatcher.find() && lineMatcher.group(1) != null && lineMatcher.group(2) != null) { - if (lineMatcher.group(2).equals("statsd")) { - long timeDeltaMillis = SystemClock.elapsedRealtime() - mStartTimeMillis; - return timeDeltaMillis + "," + convertToPss(lineMatcher.group(1)); - } - } - return null; - } - - private String convertToPss(String input) { - return input.replace(",", ""); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java deleted file mode 100644 index af7bd4d35966..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/MemoryDataRecorder.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import android.os.SystemClock; -import android.util.Log; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -public class MemoryDataRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.MemoryDataDataRecorder"; - private static final String DUMP_FILENAME = TAG + "_dump.tmp"; - - private long mStartTimeMillis; - private StringBuilder mSb; - - public MemoryDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs, - int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - } - - @Override - public void startRecording(Context context) { - mStartTimeMillis = SystemClock.elapsedRealtime(); - mSb = new StringBuilder(); - } - - @Override - public void onAlarm(Context context) { - runDumpsysStats(context, DUMP_FILENAME, "meminfo"); - readDumpData(context, DUMP_FILENAME, new MemInfoParser(mStartTimeMillis), mSb); - } - - @Override - public void stopRecording(Context context) { - writeData(context, "meminfo_", "time,pss", mSb); - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java deleted file mode 100644 index 555e6dd2d99d..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.widget.TextView; - -public abstract class NumericalWatcher implements TextWatcher { - - private static final String TAG = "loadtest.NumericalWatcher"; - - private final TextView mTextView; - private final int mMin; - private final int mMax; - private int currentValue = -1; - - public NumericalWatcher(TextView textView, int min, int max) { - mTextView = textView; - mMin = min; - mMax = max; - } - - public abstract void onNewValue(int newValue); - - @Override - final public void afterTextChanged(Editable editable) { - String s = mTextView.getText().toString(); - if (s.isEmpty()) { - return; - } - int unsanitized = Integer.parseInt(s); - int newValue = sanitize(unsanitized); - if (currentValue != newValue || unsanitized != newValue) { - currentValue = newValue; - editable.clear(); - editable.append(newValue + ""); - } - onNewValue(newValue); - } - - @Override - final public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - final public void onTextChanged(CharSequence s, int start, int before, int count) {} - - private int sanitize(int val) { - if (val > mMax) { - val = mMax; - } else if (val < mMin) { - val = mMin; - } - return val; - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java deleted file mode 100644 index 7a01adedfaa4..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -import android.annotation.Nullable; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.SystemClock; -import android.util.Log; - -import java.util.HashSet; -import java.util.Set; - -/** Prints some information about the device via Dumpsys in order to evaluate health metrics. */ -public class PerfData extends PerfDataRecorder { - - private static final String TAG = "loadtest.PerfData"; - - /** Polling period for performance snapshots like memory. */ - private static final long POLLING_PERIOD_MILLIS = 1 * 60 * 1000; - - public final static class PerfAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Intent activityIntent = new Intent(context, LoadtestActivity.class); - activityIntent.putExtra(LoadtestActivity.TYPE, LoadtestActivity.PERF_ALARM); - context.startActivity(activityIntent); - } - } - - private AlarmManager mAlarmMgr; - - /** Used to periodically poll some dumpsys data. */ - private PendingIntent mPendingIntent; - - private final Set<PerfDataRecorder> mRecorders; - - public PerfData(LoadtestActivity loadtestActivity, boolean placebo, int replication, - TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric, - boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric, - boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - mRecorders = new HashSet(); - mRecorders.add(new BatteryDataRecorder(placebo, replication, bucket, periodSecs, burst, - includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric, - includeGaugeMetric)); - mRecorders.add(new MemoryDataRecorder(placebo, replication, bucket, periodSecs, burst, - includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric, - includeGaugeMetric)); - mRecorders.add(new StatsdStatsRecorder(loadtestActivity, placebo, replication, bucket, - periodSecs, burst, includeCountMetric, includeDurationMetric, includeEventMetric, - includeValueMetric, includeGaugeMetric)); - mRecorders.add(new ValidationRecorder(loadtestActivity, placebo, replication, bucket, - periodSecs, burst, includeCountMetric, includeDurationMetric, includeEventMetric, - includeValueMetric, includeGaugeMetric)); - mAlarmMgr = (AlarmManager) loadtestActivity.getSystemService(Context.ALARM_SERVICE); - } - - public void onDestroy() { - if (mPendingIntent != null) { - mAlarmMgr.cancel(mPendingIntent); - mPendingIntent = null; - } - } - - @Override - public void startRecording(Context context) { - Intent intent = new Intent(context, PerfAlarmReceiver.class); - intent.putExtra(LoadtestActivity.TYPE, LoadtestActivity.PERF_ALARM); - mPendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); - mAlarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, -1 /* now */, - POLLING_PERIOD_MILLIS, mPendingIntent); - - for (PerfDataRecorder recorder : mRecorders) { - recorder.startRecording(context); - } - } - - @Override - public void onAlarm(Context context) { - for (PerfDataRecorder recorder : mRecorders) { - recorder.onAlarm(context); - } - } - - @Override - public void stopRecording(Context context) { - if (mPendingIntent != null) { - mAlarmMgr.cancel(mPendingIntent); - mPendingIntent = null; - } - - for (PerfDataRecorder recorder : mRecorders) { - recorder.stopRecording(context); - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java deleted file mode 100644 index 8613ac1c4796..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfDataRecorder.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; -import android.content.Context; -import android.os.Environment; -import android.util.Log; -import android.os.Debug; - -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import java.io.BufferedReader; -import java.io.Closeable; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.InputStreamReader; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - -public abstract class PerfDataRecorder { - private static final String TAG = "loadtest.PerfDataRecorder"; - - protected final String mTimeAsString; - protected final String mColumnSuffix; - - protected PerfDataRecorder(boolean placebo, int replication, TimeUnit bucket, long periodSecs, - int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - mTimeAsString = new SimpleDateFormat("YYYY_MM_dd_HH_mm_ss").format(new Date()); - mColumnSuffix = getColumnSuffix(placebo, replication, bucket, periodSecs, burst, - includeCountMetric, includeDurationMetric, includeEventMetric, includeValueMetric, - includeGaugeMetric); - } - - /** Starts recording performance data. */ - public abstract void startRecording(Context context); - - /** Called periodically. For the recorder to sample data, if needed. */ - public abstract void onAlarm(Context context); - - /** Stops recording performance data, and writes it to disk. */ - public abstract void stopRecording(Context context); - - /** Runs the dumpsys command. */ - protected void runDumpsysStats(Context context, String dumpFilename, String cmd, - String... args) { - boolean success = false; - // Call dumpsys Dump statistics to a file. - FileOutputStream fo = null; - try { - fo = context.openFileOutput(dumpFilename, Context.MODE_PRIVATE); - if (!Debug.dumpService(cmd, fo.getFD(), args)) { - Log.w(TAG, "Dumpsys failed."); - } - success = true; - } catch (IOException | SecurityException | NullPointerException e) { - // SecurityException may occur when trying to dump multi-user info. - // NPE can occur during dumpService (root cause unknown). - throw new RuntimeException(e); - } finally { - closeQuietly(fo); - } - } - - /** - * Reads a text file and parses each line, one by one. The result of the parsing is stored - * in the passed {@link StringBuffer}. - */ - protected void readDumpData(Context context, String dumpFilename, PerfParser parser, - StringBuilder sb) { - FileInputStream fi = null; - BufferedReader br = null; - try { - fi = context.openFileInput(dumpFilename); - br = new BufferedReader(new InputStreamReader(fi)); - String line = br.readLine(); - while (line != null) { - String recordLine = parser.parseLine(line); - if (recordLine != null) { - sb.append(recordLine).append('\n'); - } - line = br.readLine(); - } - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - closeQuietly(br); - } - } - - /** Writes CSV data to a file. */ - protected void writeData(Context context, String filePrefix, String columnPrefix, - StringBuilder sb) { - File dataFile = new File(getStorageDir(), filePrefix + mTimeAsString + ".csv"); - - FileWriter writer = null; - try { - writer = new FileWriter(dataFile); - writer.append(columnPrefix + mColumnSuffix + "\n"); - writer.append(sb.toString()); - writer.flush(); - Log.d(TAG, "Finished writing data at " + dataFile.getAbsolutePath()); - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - closeQuietly(writer); - } - } - - /** Gets the suffix to use in the column name for perf data. */ - private String getColumnSuffix(boolean placebo, int replication, TimeUnit bucket, - long periodSecs, int burst, boolean includeCountMetric, boolean includeDurationMetric, - boolean includeEventMetric, boolean includeValueMetric, boolean includeGaugeMetric) { - if (placebo) { - return "_placebo_p=" + periodSecs; - } - StringBuilder sb = new StringBuilder() - .append("_r=" + replication) - .append("_bkt=" + bucket) - .append("_p=" + periodSecs) - .append("_bst=" + burst) - .append("_m="); - if (includeCountMetric) { - sb.append("c"); - } - if (includeEventMetric) { - sb.append("e"); - } - if (includeDurationMetric) { - sb.append("d"); - } - if (includeGaugeMetric) { - sb.append("g"); - } - if (includeValueMetric) { - sb.append("v"); - } - return sb.toString(); - } - - private File getStorageDir() { - File file = new File(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DOCUMENTS), "loadtest/" + mTimeAsString); - if (!file.mkdirs()) { - Log.e(TAG, "Directory not created"); - } - return file; - } - - private void closeQuietly(@Nullable Closeable c) { - if (c != null) { - try { - c.close(); - } catch (IOException ignore) { - } - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfParser.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfParser.java deleted file mode 100644 index e000918fa0f7..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfParser.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.annotation.Nullable; - -public interface PerfParser { - - /** - * Parses one line of the dumpsys output, and returns a string to write to the data file, - * or null if no string should be written. - */ - @Nullable String parseLine(String line); -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java deleted file mode 100644 index 5dcce9acb401..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.util.Log; -import android.util.StatsLog; - -import java.util.ArrayList; -import java.util.List; - -/** - * Manages the pushing of atoms into logd for loadtesting. - * We rely on small number of pushed atoms, and a config with metrics based on those atoms. - * The atoms are: - * <ul> - * <li> BatteryLevelChanged - For EventMetric, CountMetric and GaugeMetric (no dimensions). - * <li> BleScanResultReceived - For CountMetric and ValueMetric, sliced by uid. - * <li> ChargingStateChanged - For DurationMetric (no dimension). - * <li> GpsScanStateChanged - For DurationMetric, sliced by uid. - * <li> ScreenStateChanged - For Conditions with no dimensions. - * <li> AudioStateChanged - For Conditions with dimensions (uid). - * </ul> - * The sequence is played over and over at a given frequency. - */ -public class SequencePusher { - private static final String TAG = "SequencePusher"; - - /** Some atoms are pushed in burst of {@code mBurst} events. */ - private final int mBurst; - - /** If this is true, we don't log anything in logd. */ - private final boolean mPlacebo; - - /** Current state in the automaton. */ - private int mCursor = 0; - - public SequencePusher(int burst, boolean placebo) { - mBurst = burst; - mPlacebo = placebo; - } - - /** - * Pushes the next atom to logd. - * This follows a small automaton which makes the right events and conditions overlap: - * (0) Push a burst of BatteryLevelChanged atoms. - * (1) Push a burst of BleScanResultReceived atoms. - * (2) Push ChargingStateChanged with BATTERY_STATUS_CHARGING once. - * (3) Push a burst of GpsScanStateChanged atoms with ON, with a different uid each time. - * (4) Push ChargingStateChanged with BATTERY_STATUS_NOT_CHARGING once. - * (5) Push a burst GpsScanStateChanged atoms with OFF, with a different uid each time. - * (6) Push ScreenStateChanged with STATE_ON once. - * (7) Push a burst of AudioStateChanged with ON, with a different uid each time. - * (8) Repeat steps (0)-(5). - * (9) Push ScreenStateChanged with STATE_OFF once. - * (10) Push a burst of AudioStateChanged with OFF, with a different uid each time. - * and repeat. - */ - public void next() { - Log.d(TAG, "Next step: " + mCursor); - if (mPlacebo) { - return; - } - switch (mCursor) { - case 0: - case 8: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, 50 + i /* battery_level */); - } - break; - case 1: - case 9: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED, i /* uid */, - 100 /* num_of_results */); - } - break; - case 2: - case 10: - StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_CHARGING - /* charging_state */); - break; - case 3: - case 11: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */, - StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON /* state */); - } - break; - case 4: - case 12: - StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING - /* charging_state */); - break; - case 5: - case 13: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */, - StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF /* state */); - } - break; - case 6: - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_ON /* display_state */); - break; - case 7: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */, - StatsLog.AUDIO_STATE_CHANGED__STATE__ON /* state */); - } - break; - case 14: - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */); - break; - case 15: - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */, - StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */); - } - break; - default: - } - mCursor++; - if (mCursor > 15) { - mCursor = 0; - } - } - - /** - * Properly finishes in order to be close all conditions and durations. - */ - public void finish() { - // Screen goes back to off. This will ensure that conditions get back to false. - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, - StatsLog.SCREEN_STATE_CHANGED__STATE__DISPLAY_STATE_OFF /* display_state */); - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */, - StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */); - } - // Stop charging, to ensure the corresponding durations are closed. - StatsLog.write(StatsLog.CHARGING_STATE_CHANGED, - StatsLog.CHARGING_STATE_CHANGED__STATE__BATTERY_STATUS_NOT_CHARGING - /* charging_state */); - // Stop scanning GPS, to ensure the corresponding conditions get back to false. - for (int i = 0; i < mBurst; i++) { - StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */, - StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF /* state */); - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java deleted file mode 100644 index 3939e7e0b2fa..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/StatsdStatsRecorder.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import com.android.os.StatsLog.StatsdStatsReport; -import com.android.internal.os.StatsdConfigProto.TimeUnit; - -public class StatsdStatsRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.StatsdStatsRecorder"; - - private final LoadtestActivity mLoadtestActivity; - - public StatsdStatsRecorder(LoadtestActivity loadtestActivity, boolean placebo, int replication, - TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric, - boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric, - boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - mLoadtestActivity = loadtestActivity; - } - - @Override - public void startRecording(Context context) { - // Nothing to do. - } - - @Override - public void onAlarm(Context context) { - // Nothing to do. - } - - @Override - public void stopRecording(Context context) { - StatsdStatsReport metadata = mLoadtestActivity.getMetadata(); - if (metadata != null) { - int numConfigs = metadata.getConfigStatsCount(); - StringBuilder sb = new StringBuilder(); - StatsdStatsReport.ConfigStats configStats = metadata.getConfigStats(numConfigs - 1); - sb.append("metric_count,") - .append(configStats.getMetricCount() + "\n") - .append("condition_count,") - .append(configStats.getConditionCount() + "\n") - .append("matcher_count,") - .append(configStats.getMatcherCount() + "\n"); - writeData(context, "statsdstats_", "stat,value", sb); - } - } -} diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java deleted file mode 100644 index d9f0ca9d2461..000000000000 --- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ValidationRecorder.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2017 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.statsd.loadtest; - -import android.content.Context; -import android.util.Log; -import com.android.os.StatsLog.ConfigMetricsReport; -import com.android.os.StatsLog.EventMetricData; -import com.android.os.StatsLog.StatsLogReport; -import com.android.internal.os.StatsdConfigProto.TimeUnit; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Checks the correctness of the stats. - */ -public class ValidationRecorder extends PerfDataRecorder { - private static final String TAG = "loadtest.ValidationRecorder"; - - private final LoadtestActivity mLoadtestActivity; - - public ValidationRecorder(LoadtestActivity loadtestActivity, boolean placebo, int replication, - TimeUnit bucket, long periodSecs, int burst, boolean includeCountMetric, - boolean includeDurationMetric, boolean includeEventMetric, boolean includeValueMetric, - boolean includeGaugeMetric) { - super(placebo, replication, bucket, periodSecs, burst, includeCountMetric, - includeDurationMetric, includeEventMetric, includeValueMetric, includeGaugeMetric); - mLoadtestActivity = loadtestActivity; - } - - @Override - public void startRecording(Context context) { - // Nothing to do. - } - - @Override - public void onAlarm(Context context) { - validateData(); - } - - @Override - public void stopRecording(Context context) { - validateData(); - } - - private void validateData() { - // The code below is commented out because it calls getData, which has the side-effect - // of clearing statsd's data buffer. - /* - List<ConfigMetricsReport> reports = mLoadtestActivity.getData(); - if (reports != null) { - Log.d(TAG, "GOT DATA"); - for (ConfigMetricsReport report : reports) { - for (StatsLogReport logReport : report.getMetricsList()) { - if (!logReport.hasMetricId()) { - Log.e(TAG, "Metric missing name."); - } - } - } - } - */ - } - - private void validateEventBatteryLevelChanges(StatsLogReport logReport) { - Log.d(TAG, "Validating " + logReport.getMetricId()); - if (logReport.hasEventMetrics()) { - Log.d(TAG, "Num events captured: " + logReport.getEventMetrics().getDataCount()); - for (EventMetricData data : logReport.getEventMetrics().getDataList()) { - Log.d(TAG, " Event : " + data.getAtom()); - } - } else { - Log.d(TAG, "Metric is invalid"); - } - } - - private void validateEventBatteryLevelChangesWhileScreenIsOn(StatsLogReport logReport) { - Log.d(TAG, "Validating " + logReport.getMetricId()); - } -} diff --git a/config/boot-profile.txt b/config/boot-profile.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/config/boot-profile.txt diff --git a/tools/preload2/src/com/android/preload/classdataretrieval/ClassDataRetriever.java b/core/java/android/accessibilityservice/AccessibilityGestureInfo.aidl index f04360fc1942..2539051f4069 100644 --- a/tools/preload2/src/com/android/preload/classdataretrieval/ClassDataRetriever.java +++ b/core/java/android/accessibilityservice/AccessibilityGestureInfo.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,6 @@ * limitations under the License. */ -package com.android.preload.classdataretrieval; +package android.accessibilityservice; -import com.android.ddmlib.Client; - -import java.util.Map; - -/** - * Retrieve a class-to-classloader map for loaded classes from the client. - */ -public interface ClassDataRetriever { - - public Map<String, String> getClassData(Client client); -} +parcelable AccessibilityGestureInfo; diff --git a/core/java/android/accessibilityservice/AccessibilityGestureInfo.java b/core/java/android/accessibilityservice/AccessibilityGestureInfo.java new file mode 100644 index 000000000000..dc50a4c6c633 --- /dev/null +++ b/core/java/android/accessibilityservice/AccessibilityGestureInfo.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.accessibilityservice; + + +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_UP; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT_AND_DOWN; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT_AND_RIGHT; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_LEFT_AND_UP; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT_AND_DOWN; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT_AND_LEFT; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT; +import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.TestApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * This class describes the gesture information including gesture id and which display it happens + * on. + * <p> + * <strong>Note:</strong> Accessibility services setting the + * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} + * flag can receive gestures. + * + * @see AccessibilityService#onGesture(AccessibilityGestureInfo) + */ + +public final class AccessibilityGestureInfo implements Parcelable { + + /** @hide */ + @IntDef(prefix = { "GESTURE_" }, value = { + GESTURE_SWIPE_UP, + GESTURE_SWIPE_UP_AND_LEFT, + GESTURE_SWIPE_UP_AND_DOWN, + GESTURE_SWIPE_UP_AND_RIGHT, + GESTURE_SWIPE_DOWN, + GESTURE_SWIPE_DOWN_AND_LEFT, + GESTURE_SWIPE_DOWN_AND_UP, + GESTURE_SWIPE_DOWN_AND_RIGHT, + GESTURE_SWIPE_LEFT, + GESTURE_SWIPE_LEFT_AND_UP, + GESTURE_SWIPE_LEFT_AND_RIGHT, + GESTURE_SWIPE_LEFT_AND_DOWN, + GESTURE_SWIPE_RIGHT, + GESTURE_SWIPE_RIGHT_AND_UP, + GESTURE_SWIPE_RIGHT_AND_LEFT, + GESTURE_SWIPE_RIGHT_AND_DOWN + }) + @Retention(RetentionPolicy.SOURCE) + public @interface GestureType {} + + @GestureType + private final int mGestureId; + private final int mDisplayId; + + /** @hide */ + @TestApi + public AccessibilityGestureInfo(int gestureId, int displayId) { + mGestureId = gestureId; + mDisplayId = displayId; + } + + private AccessibilityGestureInfo(@NonNull Parcel parcel) { + mGestureId = parcel.readInt(); + mDisplayId = parcel.readInt(); + } + + /** + * Returns the display id of the received-gesture display, for use with + * {@link android.hardware.display.DisplayManager#getDisplay(int)}. + * + * @return the display id. + */ + public int getDisplayId() { + return mDisplayId; + } + + /** + * Returns performed gesture id. + * + * @return the performed gesture id. + * + */ + @GestureType public int getGestureId() { + return mGestureId; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder("AccessibilityGestureInfo["); + stringBuilder.append("gestureId: ").append(mGestureId); + stringBuilder.append(", "); + stringBuilder.append("displayId: ").append(mDisplayId); + stringBuilder.append(']'); + return stringBuilder.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mGestureId); + parcel.writeInt(mDisplayId); + } + + /** + * @see Parcelable.Creator + */ + public static final @NonNull Parcelable.Creator<AccessibilityGestureInfo> CREATOR = + new Parcelable.Creator<AccessibilityGestureInfo>() { + public AccessibilityGestureInfo createFromParcel(Parcel parcel) { + return new AccessibilityGestureInfo(parcel); + } + + public AccessibilityGestureInfo[] newArray(int size) { + return new AccessibilityGestureInfo[size]; + } + }; + +} diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 4aafa53805e1..827e5408403a 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -309,7 +309,7 @@ public abstract class AccessibilityService extends Service { * Name under which an AccessibilityService component publishes information * about itself. This meta-data must reference an XML resource containing an * <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code> - * tag. This is a a sample XML file configuring an accessibility service: + * tag. This is a sample XML file configuring an accessibility service: * <pre> <accessibility-service * android:accessibilityEventTypes="typeViewClicked|typeViewFocused" * android:packageNames="foo.bar, foo.baz" @@ -381,7 +381,8 @@ public abstract class AccessibilityService extends Service { void onInterrupt(); void onServiceConnected(); void init(int connectionId, IBinder windowToken); - boolean onGesture(int gestureId); + /** The detected gesture information for different displays */ + boolean onGesture(AccessibilityGestureInfo gestureInfo); boolean onKeyEvent(KeyEvent event); /** Magnification changed callbacks for different displays */ void onMagnificationChanged(int displayId, @NonNull Region region, @@ -514,17 +515,18 @@ public abstract class AccessibilityService extends Service { } /** - * Called by the system when the user performs a specific gesture on the - * touch screen. + * Called by {@link #onGesture(AccessibilityGestureInfo)} when the user performs a specific + * gesture on the default display. * * <strong>Note:</strong> To receive gestures an accessibility service must * request that the device is in touch exploration mode by setting the - * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} + * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} * flag. * * @param gestureId The unique id of the performed gesture. * * @return Whether the gesture was handled. + * @deprecated Override {@link #onGesture(AccessibilityGestureInfo)} instead. * * @see #GESTURE_SWIPE_UP * @see #GESTURE_SWIPE_UP_AND_LEFT @@ -543,11 +545,36 @@ public abstract class AccessibilityService extends Service { * @see #GESTURE_SWIPE_RIGHT_AND_LEFT * @see #GESTURE_SWIPE_RIGHT_AND_DOWN */ + @Deprecated protected boolean onGesture(int gestureId) { return false; } /** + * Called by the system when the user performs a specific gesture on the + * specific touch screen. + *<p> + * <strong>Note:</strong> To receive gestures an accessibility service must + * request that the device is in touch exploration mode by setting the + * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} + * flag. + *<p> + * <strong>Note:</strong> The default implementation calls {@link #onGesture(int)} when the + * touch screen is default display. + * + * @param gestureInfo The information of gesture. + * + * @return Whether the gesture was handled. + * + */ + public boolean onGesture(@NonNull AccessibilityGestureInfo gestureInfo) { + if (gestureInfo.getDisplayId() == Display.DEFAULT_DISPLAY) { + onGesture(gestureInfo.getGestureId()); + } + return false; + } + + /** * Callback that allows an accessibility service to observe the key events * before they are passed to the rest of the system. This means that the events * are first delivered here before they are passed to the device policy, the @@ -777,8 +804,8 @@ public abstract class AccessibilityService extends Service { callback, handler); mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo); } - connection.sendGesture(mGestureStatusCallbackSequence, - new ParceledListSlice<>(steps)); + connection.dispatchGesture(mGestureStatusCallbackSequence, + new ParceledListSlice<>(steps), gesture.getDisplayId()); } } catch (RemoteException re) { throw new RuntimeException(re); @@ -1673,8 +1700,8 @@ public abstract class AccessibilityService extends Service { } @Override - public boolean onGesture(int gestureId) { - return AccessibilityService.this.onGesture(gestureId); + public boolean onGesture(AccessibilityGestureInfo gestureInfo) { + return AccessibilityService.this.onGesture(gestureInfo); } @Override @@ -1773,8 +1800,9 @@ public abstract class AccessibilityService extends Service { mCaller.sendMessage(message); } - public void onGesture(int gestureId) { - Message message = mCaller.obtainMessageI(DO_ON_GESTURE, gestureId); + @Override + public void onGesture(AccessibilityGestureInfo gestureInfo) { + Message message = mCaller.obtainMessageO(DO_ON_GESTURE, gestureInfo); mCaller.sendMessage(message); } @@ -1887,8 +1915,7 @@ public abstract class AccessibilityService extends Service { case DO_ON_GESTURE: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { - final int gestureId = message.arg1; - mCallback.onGesture(gestureId); + mCallback.onGesture((AccessibilityGestureInfo) message.obj); } } return; diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java index a3e7ad5da9b1..3b79d217c513 100644 --- a/core/java/android/accessibilityservice/GestureDescription.java +++ b/core/java/android/accessibilityservice/GestureDescription.java @@ -23,6 +23,7 @@ import android.graphics.PathMeasure; import android.graphics.RectF; import android.os.Parcel; import android.os.Parcelable; +import android.view.Display; import com.android.internal.util.Preconditions; @@ -33,7 +34,7 @@ import java.util.List; * Accessibility services with the * {@link android.R.styleable#AccessibilityService_canPerformGestures} property can dispatch * gestures. This class describes those gestures. Gestures are made up of one or more strokes. - * Gestures are immutable once built. + * Gestures are immutable once built and will be dispatched to the specified display. * <p> * Spatial dimensions throughout are in screen pixels. Time is measured in milliseconds. */ @@ -48,6 +49,7 @@ public final class GestureDescription { private final List<StrokeDescription> mStrokes = new ArrayList<>(); private final float[] mTempPos = new float[2]; + private final int mDisplayId; /** * Get the upper limit for the number of strokes a gesture may contain. @@ -67,10 +69,17 @@ public final class GestureDescription { return MAX_GESTURE_DURATION_MS; } - private GestureDescription() {} + private GestureDescription() { + this(new ArrayList<>()); + } private GestureDescription(List<StrokeDescription> strokes) { + this(strokes, Display.DEFAULT_DISPLAY); + } + + private GestureDescription(List<StrokeDescription> strokes, int displayId) { mStrokes.addAll(strokes); + mDisplayId = displayId; } /** @@ -94,6 +103,16 @@ public final class GestureDescription { } /** + * Returns the ID of the display this gesture is sent on, for use with + * {@link android.hardware.display.DisplayManager#getDisplay(int)}. + * + * @return The logical display id. + */ + public int getDisplayId() { + return mDisplayId; + } + + /** * Return the smallest key point (where a path starts or ends) that is at least a specified * offset * @param offset the minimum start time @@ -160,9 +179,10 @@ public final class GestureDescription { public static class Builder { private final List<StrokeDescription> mStrokes = new ArrayList<>(); + private int mDisplayId = Display.DEFAULT_DISPLAY; /** - * Add a stroke to the gesture description. Up to + * Adds a stroke to the gesture description. Up to * {@link GestureDescription#getMaxStrokeCount()} paths may be * added to a gesture, and the total gesture duration (earliest path start time to latest * path end time) may not exceed {@link GestureDescription#getMaxGestureDuration()}. @@ -187,11 +207,23 @@ public final class GestureDescription { return this; } + /** + * Sets the id of the display to dispatch gestures. + * + * @param displayId The logical display id + * + * @return this + */ + public @NonNull Builder setDisplayId(int displayId) { + mDisplayId = displayId; + return this; + } + public GestureDescription build() { if (mStrokes.size() == 0) { throw new IllegalStateException("Gestures must have at least one stroke"); } - return new GestureDescription(mStrokes); + return new GestureDescription(mStrokes, mDisplayId); } } diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl index 1dae4fca111e..407ba59c3297 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl @@ -20,6 +20,7 @@ import android.accessibilityservice.IAccessibilityServiceConnection; import android.graphics.Region; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityWindowInfo; +import android.accessibilityservice.AccessibilityGestureInfo; import android.view.KeyEvent; /** @@ -35,7 +36,7 @@ import android.view.KeyEvent; void onInterrupt(); - void onGesture(int gesture); + void onGesture(in AccessibilityGestureInfo gestureInfo); void clearAccessibilityCache(); diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl index c8e01321812c..1ca07dd6ed23 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl @@ -95,6 +95,8 @@ interface IAccessibilityServiceConnection { void sendGesture(int sequence, in ParceledListSlice gestureSteps); + void dispatchGesture(int sequence, in ParceledListSlice gestureSteps, int displayId); + boolean isFingerprintGestureDetectionAvailable(); IBinder getOverlayWindowToken(int displayid); diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 755f0476d9ba..415ec64dc126 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -386,9 +386,15 @@ public class ActivityView extends ViewGroup { // Also report this geometry information to InputMethodManagerService. // TODO(b/115693908): Unify this logic into the above WMS-based one. + // TODO(b/138175283): Address the location update when the host of this view is + // moving. final Matrix matrix = new Matrix(); + final int[] locationOnScreen = new int[2]; + getLocationOnScreen(locationOnScreen); + final int dx = locationOnScreen[0]; + final int dy = locationOnScreen[1]; matrix.set(getMatrix()); - matrix.postTranslate(x, y); + matrix.postTranslate(dx, dy); mContext.getSystemService(InputMethodManager.class) .reportActivityView(displayId, matrix); } diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 2957309094f6..47b784b3eaaf 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -153,6 +153,7 @@ interface IActivityTaskManager { void moveTaskToFront(in IApplicationThread app, in String callingPackage, int task, int flags, in Bundle options); int getTaskForActivity(in IBinder token, in boolean onlyRoot); + /** Finish all activities that were started for result from the specified activity. */ void finishSubActivity(in IBinder token, in String resultWho, int requestCode); ParceledListSlice getRecentTasks(int maxNum, int flags, int userId); boolean willActivityBeVisible(in IBinder token); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 5aa1f8f07f60..372eab259f4c 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -5437,10 +5437,11 @@ public class Notification implements Parcelable /** * Construct a RemoteViews for the display in public contexts like on the lockscreen. * + * @param isLowPriority is this notification low priority * @hide */ @UnsupportedAppUsage - public RemoteViews makePublicContentView() { + public RemoteViews makePublicContentView(boolean isLowPriority) { if (mN.publicVersion != null) { final Builder builder = recoverBuilder(mContext, mN.publicVersion); return builder.createContentView(); @@ -5467,7 +5468,11 @@ public class Notification implements Parcelable } mN.extras = publicExtras; RemoteViews view; - view = makeNotificationHeader(); + StandardTemplateParams params = mParams.reset().fillTextsFrom(this); + if (isLowPriority) { + params.forceDefaultColor(); + } + view = makeNotificationHeader(params); view.setBoolean(R.id.notification_header, "setExpandOnlyOnButton", true); mN.extras = savedBundle; mN.mLargeIcon = largeIcon; diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 3935628b707f..2b74b99c8071 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -16,6 +16,7 @@ package android.app; +import android.accessibilityservice.AccessibilityGestureInfo; import android.accessibilityservice.AccessibilityService.Callbacks; import android.accessibilityservice.AccessibilityService.IAccessibilityServiceClientWrapper; import android.accessibilityservice.AccessibilityServiceInfo; @@ -1232,7 +1233,7 @@ public final class UiAutomation { } @Override - public boolean onGesture(int gestureId) { + public boolean onGesture(AccessibilityGestureInfo gestureInfo) { /* do nothing */ return false; } diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 05833b5f571d..5d00f09501b0 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -126,6 +126,17 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { "android.bluetooth.headsetclient.profile.action.RESULT"; /** + * Intent that notifies about vendor specific event arrival. Events not defined in + * HFP spec will be matched with supported vendor event list and this intent will + * be broadcasted upon a match. Supported vendor events are of format of + * of "+eventCode" or "+eventCode=xxxx" or "+eventCode:=xxxx". + * Vendor event can be a response to an vendor specific command or unsolicited. + * + */ + public static final String ACTION_VENDOR_SPECIFIC_HEADSETCLIENT_EVENT = + "android.bluetooth.headsetclient.profile.action.VENDOR_SPECIFIC_EVENT"; + + /** * Intent that notifies about the number attached to the last voice tag * recorded on AG. * @@ -243,6 +254,28 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { public static final String EXTRA_CME_CODE = "android.bluetooth.headsetclient.extra.CME_CODE"; + /** + * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that + * indicates vendor ID. + */ + public static final String EXTRA_VENDOR_ID = + "android.bluetooth.headsetclient.extra.VENDOR_ID"; + + /** + * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that + * indicates vendor event code. + */ + public static final String EXTRA_VENDOR_EVENT_CODE = + "android.bluetooth.headsetclient.extra.VENDOR_EVENT_CODE"; + + /** + * Extra for VENDOR_SPECIFIC_HEADSETCLIENT_EVENT intent that + * contains full vendor event including event code and full arguments. + */ + public static final String EXTRA_VENDOR_EVENT_FULL_ARGS = + "android.bluetooth.headsetclient.extra.VENDOR_EVENT_FULL_ARGS"; + + /* Extras for AG_FEATURES, extras type is boolean */ // TODO verify if all of those are actually useful /** @@ -588,6 +621,31 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { } /** + * Send vendor specific AT command. + * + * @param device remote device + * @param vendorId vendor number by Bluetooth SIG + * @param atCommand command to be sent. It start with + prefix and only one command at one time. + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise. + */ + public boolean sendVendorAtCommand(BluetoothDevice device, int vendorId, + String atCommand) { + if (DBG) log("sendVendorSpecificCommand()"); + final IBluetoothHeadsetClient service = + getService(); + if (service != null && isEnabled() && isValidDevice(device)) { + try { + return service.sendVendorAtCommand(device, vendorId, atCommand); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (service == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** * Stops voice recognition. * * @param device remote device diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 4d8a0c46508e..895eba6cdec2 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2044,6 +2044,30 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device supports Open Mobile API capable UICC-based secure + * elements. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_SE_OMAPI_UICC = "android.hardware.se.omapi.uicc"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device supports Open Mobile API capable eSE-based secure + * elements. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_SE_OMAPI_ESE = "android.hardware.se.omapi.ese"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device supports Open Mobile API capable SD-based secure + * elements. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_SE_OMAPI_SD = "android.hardware.se.omapi.sd"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device supports the OpenGL ES * <a href="http://www.khronos.org/registry/gles/extensions/ANDROID/ANDROID_extension_pack_es31a.txt"> * Android Extension Pack</a>. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index e690a7fd783b..a4933ef1703f 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -66,6 +66,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.FileUtils; @@ -2445,6 +2446,8 @@ public class PackageParser { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; + } else if (tagName.equals("queries")) { + parseQueries(pkg, res, parser, flags, outError); } else { Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() + " at " + mArchiveSourcePath + " " @@ -3538,6 +3541,9 @@ public class PackageParser { owner.mRequiredAccountType = requiredAccountType; } + owner.mForceQueryable = + sa.getBoolean(R.styleable.AndroidManifestApplication_forceQueryable, false); + if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_debuggable, false)) { @@ -3953,7 +3959,6 @@ public class PackageParser { ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL; } XmlUtils.skipCurrentTag(parser); - } else { if (!RIGID_PARSER) { Slog.w(TAG, "Unknown element under <application>: " + tagName @@ -4000,6 +4005,67 @@ public class PackageParser { return true; } + private boolean parseQueries(Package owner, Resources res, XmlResourceParser parser, int flags, + String[] outError) + throws IOException, XmlPullParserException { + + final int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + if (parser.getName().equals("intent")) { + QueriesIntentInfo intentInfo = new QueriesIntentInfo(); + if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/, + intentInfo, outError)) { + return false; + } + Intent intent = new Intent(); + if (intentInfo.countActions() != 1) { + outError[0] = "intent tags must contain exactly one action."; + return false; + } + intent.setAction(intentInfo.getAction(0)); + for (int i = 0, max = intentInfo.countCategories(); i < max; i++) { + intent.addCategory(intentInfo.getCategory(i)); + } + Uri data = null; + String dataType = null; + if (intentInfo.countDataTypes() > 1) { + outError[0] = "intent tag may have at most one data type."; + return false; + } + if (intentInfo.countDataSchemes() > 1) { + outError[0] = "intent tag may have at most one data scheme."; + return false; + } + if (intentInfo.countDataTypes() == 1) { + data = Uri.fromParts(intentInfo.getDataType(0), "", null); + } + if (intentInfo.countDataSchemes() == 1) { + dataType = intentInfo.getDataScheme(0); + } + intent.setDataAndType(data, dataType); + owner.mQueriesIntents = ArrayUtils.add(owner.mQueriesIntents, intent); + } else if (parser.getName().equals("package")) { + final TypedArray sa = res.obtainAttributes(parser, + com.android.internal.R.styleable.AndroidManifestQueriesPackage); + final String packageName = + sa.getString(R.styleable.AndroidManifestQueriesPackage_name); + if (TextUtils.isEmpty(packageName)) { + outError[0] = "Package name is missing from package tag."; + return false; + } + owner.mQueriesPackages = + ArrayUtils.add(owner.mQueriesPackages, packageName.intern()); + } + } + return true; + } + /** * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI */ @@ -6514,6 +6580,9 @@ public class PackageParser { // The major version code declared for this package. public int mVersionCodeMajor; + // Whether the package declares that it should be queryable by all normal apps on device. + public boolean mForceQueryable; + // Return long containing mVersionCode and mVersionCodeMajor. public long getLongVersionCode() { return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode); @@ -6619,6 +6688,9 @@ public class PackageParser { /** Whether or not the package is a stub and must be replaced by the full version. */ public boolean isStub; + public ArrayList<String> mQueriesPackages; + public ArrayList<Intent> mQueriesIntents; + @UnsupportedAppUsage public Package(String packageName) { this.packageName = packageName; @@ -7122,6 +7194,9 @@ public class PackageParser { use32bitAbi = (dest.readInt() == 1); restrictUpdateHash = dest.createByteArray(); visibleToInstantApps = dest.readInt() == 1; + mForceQueryable = dest.readBoolean(); + mQueriesIntents = dest.createTypedArrayList(Intent.CREATOR); + mQueriesPackages = dest.createStringArrayList(); } private static void internStringArrayList(List<String> list) { @@ -7247,6 +7322,9 @@ public class PackageParser { dest.writeInt(use32bitAbi ? 1 : 0); dest.writeByteArray(restrictUpdateHash); dest.writeInt(visibleToInstantApps ? 1 : 0); + dest.writeBoolean(mForceQueryable); + dest.writeTypedList(mQueriesIntents); + dest.writeList(mQueriesPackages); } @@ -8257,6 +8335,8 @@ public class PackageParser { } } + public static final class QueriesIntentInfo extends IntentInfo {} + public final static class ActivityIntentInfo extends IntentInfo { @UnsupportedAppUsage public Activity activity; diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java index af66dc161343..d8110f33d723 100644 --- a/core/java/android/hardware/biometrics/BiometricManager.java +++ b/core/java/android/hardware/biometrics/BiometricManager.java @@ -129,6 +129,25 @@ public class BiometricManager { } /** + * @hide + * @param userId + * @return + */ + @RequiresPermission(USE_BIOMETRIC_INTERNAL) + public boolean hasEnrolledBiometrics(int userId) { + if (mService != null) { + try { + return mService.hasEnrolledBiometrics(userId); + } catch (RemoteException e) { + Slog.w(TAG, "Remote exception in hasEnrolledBiometrics(): " + e); + return false; + } + } else { + return false; + } + } + + /** * Listens for changes to biometric eligibility on keyguard from user settings. * @param callback * @hide diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl index 18c14cb835a8..f0a0b2f0235f 100644 --- a/core/java/android/hardware/biometrics/IBiometricService.aidl +++ b/core/java/android/hardware/biometrics/IBiometricService.aidl @@ -42,6 +42,9 @@ interface IBiometricService { // Checks if biometrics can be used. int canAuthenticate(String opPackageName, int userId); + // Checks if any biometrics are enrolled. + boolean hasEnrolledBiometrics(int userId); + // Register callback for when keyguard biometric eligibility changes. void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback); diff --git a/core/java/android/hardware/radio/ProgramList.java b/core/java/android/hardware/radio/ProgramList.java index 623d5ec434fe..f4fd1b6fb75f 100644 --- a/core/java/android/hardware/radio/ProgramList.java +++ b/core/java/android/hardware/radio/ProgramList.java @@ -369,6 +369,33 @@ public final class ProgramList implements AutoCloseable { public boolean areModificationsExcluded() { return mExcludeModifications; } + + @Override + public int hashCode() { + return Objects.hash(mIdentifierTypes, mIdentifiers, mIncludeCategories, + mExcludeModifications); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Filter)) return false; + Filter other = (Filter) obj; + + if (mIncludeCategories != other.mIncludeCategories) return false; + if (mExcludeModifications != other.mExcludeModifications) return false; + if (!Objects.equals(mIdentifierTypes, other.mIdentifierTypes)) return false; + if (!Objects.equals(mIdentifiers, other.mIdentifiers)) return false; + return true; + } + + @Override + public String toString() { + return "Filter [mIdentifierTypes=" + mIdentifierTypes + + ", mIdentifiers=" + mIdentifiers + + ", mIncludeCategories=" + mIncludeCategories + + ", mExcludeModifications=" + mExcludeModifications + "]"; + } } /** @@ -436,5 +463,24 @@ public final class ProgramList implements AutoCloseable { public @NonNull Set<ProgramSelector.Identifier> getRemoved() { return mRemoved; } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Chunk)) return false; + Chunk other = (Chunk) obj; + + if (mPurge != other.mPurge) return false; + if (mComplete != other.mComplete) return false; + if (!Objects.equals(mModified, other.mModified)) return false; + if (!Objects.equals(mRemoved, other.mRemoved)) return false; + return true; + } + + @Override + public String toString() { + return "Chunk [mPurge=" + mPurge + ", mComplete=" + mComplete + + ", mModified=" + mModified + ", mRemoved=" + mRemoved + "]"; + } } } diff --git a/core/java/android/hardware/radio/RadioMetadata.java b/core/java/android/hardware/radio/RadioMetadata.java index b60c13631edd..c135c8a73abc 100644 --- a/core/java/android/hardware/radio/RadioMetadata.java +++ b/core/java/android/hardware/radio/RadioMetadata.java @@ -258,6 +258,11 @@ public final class RadioMetadata implements Parcelable { private final Bundle mBundle; @Override + public int hashCode() { + return mBundle.hashCode(); + } + + @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof RadioMetadata)) return false; diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java index 2f68eb475e7a..d862d6022154 100644 --- a/core/java/android/provider/CalendarContract.java +++ b/core/java/android/provider/CalendarContract.java @@ -40,7 +40,7 @@ import android.database.DatabaseUtils; import android.net.Uri; import android.os.RemoteException; import android.text.format.DateUtils; -import android.text.format.Time; +import android.text.format.TimeMigrationUtils; import android.util.Log; import com.android.internal.util.Preconditions; @@ -1680,7 +1680,7 @@ public final class CalendarContract { * <h3>Writing to Events</h3> There are further restrictions on all Updates * and Inserts in the Events table: * <ul> - * <li>If allDay is set to 1 eventTimezone must be {@link Time#TIMEZONE_UTC} + * <li>If allDay is set to 1 eventTimezone must be "UTC" * and the time must correspond to a midnight boundary.</li> * <li>Exceptions are not allowed to recur. If rrule or rdate is not empty, * original_id and original_sync_id must be empty.</li> @@ -2608,9 +2608,7 @@ public final class CalendarContract { @UnsupportedAppUsage public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) { if (DEBUG) { - Time time = new Time(); - time.set(alarmTime); - String schedTime = time.format(" %a, %b %d, %Y %I:%M%P"); + String schedTime = TimeMigrationUtils.formatMillisWithFixedFormat(alarmTime); Log.d(TAG, "Schedule alarm at " + alarmTime + " " + schedTime); } diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java index 5a14092c95a8..f7fd89d7d819 100644 --- a/core/java/android/text/format/TimeFormatter.java +++ b/core/java/android/text/format/TimeFormatter.java @@ -26,6 +26,9 @@ import libcore.icu.LocaleData; import libcore.util.ZoneInfo; import java.nio.CharBuffer; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.Formatter; import java.util.Locale; import java.util.TimeZone; @@ -86,6 +89,59 @@ class TimeFormatter { } /** + * The implementation of {@link TimeMigrationUtils#formatMillisWithFixedFormat(long)} for + * 2038-safe formatting with the pattern "%Y-%m-%d %H:%M:%S" and including the historic + * incorrect digit localization behavior. + */ + String formatMillisWithFixedFormat(long timeMillis) { + // This method is deliberately not a general purpose replacement for + // format(String, ZoneInfo.WallTime, ZoneInfo): It hard-codes the pattern used; many of the + // pattern characters supported by Time.format() have unusual behavior which would make + // using java.time.format or similar packages difficult. It would be a lot of work to share + // behavior and many internal Android usecases can be covered by this common pattern + // behavior. + + // No need to worry about overflow / underflow: long millis is representable by Instant and + // LocalDateTime with room to spare. + Instant instant = Instant.ofEpochMilli(timeMillis); + + // Date/times are calculated in the current system default time zone. + LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); + + // You'd think it would be as simple as: + // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", locale); + // return formatter.format(localDateTime); + // but we retain Time's behavior around digits. + + StringBuilder stringBuilder = new StringBuilder(19); + + // This effectively uses the US locale because number localization is handled separately + // (see below). + stringBuilder.append(localDateTime.getYear()); + stringBuilder.append('-'); + append2DigitNumber(stringBuilder, localDateTime.getMonthValue()); + stringBuilder.append('-'); + append2DigitNumber(stringBuilder, localDateTime.getDayOfMonth()); + stringBuilder.append(' '); + append2DigitNumber(stringBuilder, localDateTime.getHour()); + stringBuilder.append(':'); + append2DigitNumber(stringBuilder, localDateTime.getMinute()); + stringBuilder.append(':'); + append2DigitNumber(stringBuilder, localDateTime.getSecond()); + + String result = stringBuilder.toString(); + return localizeDigits(result); + } + + /** Zero-pads value as needed to achieve a 2-digit number. */ + private static void append2DigitNumber(StringBuilder builder, int value) { + if (value < 10) { + builder.append('0'); + } + builder.append(value); + } + + /** * Format the specified {@code wallTime} using {@code pattern}. The output is returned. */ public String format(String pattern, ZoneInfo.WallTime wallTime, ZoneInfo zoneInfo) { @@ -99,12 +155,9 @@ class TimeFormatter { formatInternal(pattern, wallTime, zoneInfo); String result = stringBuilder.toString(); - // This behavior is the source of a bug since some formats are defined as being - // in ASCII and not localized. - if (localeData.zeroDigit != '0') { - result = localizeDigits(result); - } - return result; + // The localizeDigits() behavior is the source of a bug since some formats are defined + // as being in ASCII and not localized. + return localizeDigits(result); } finally { outputBuilder = null; numberFormatter = null; @@ -112,6 +165,10 @@ class TimeFormatter { } private String localizeDigits(String s) { + if (localeData.zeroDigit == '0') { + return s; + } + int length = s.length(); int offsetToLocalizedDigits = localeData.zeroDigit - '0'; StringBuilder result = new StringBuilder(length); diff --git a/core/java/android/text/format/TimeMigrationUtils.java b/core/java/android/text/format/TimeMigrationUtils.java new file mode 100644 index 000000000000..17bac8d67b26 --- /dev/null +++ b/core/java/android/text/format/TimeMigrationUtils.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.text.format; + +/** + * Logic to ease migration away from {@link Time} in Android internal code. {@link Time} is + * afflicted by the Y2038 issue and deprecated. The methods here are intended to allow minimal + * changes to classes that use {@link Time} for common behavior. + * + * @hide + */ +public class TimeMigrationUtils { + + private TimeMigrationUtils() {} + + /** + * A Y2038-safe replacement for various users of the {@link Time#format(String)} with the + * pattern "%Y-%m-%d %H:%M:%S". Note, this method retains the unusual localization behavior + * originally implemented by Time, which can lead to non-latin numbers being produced if the + * default locale does not use latin numbers. + */ + public static String formatMillisWithFixedFormat(long timeMillis) { + // Delegate to TimeFormatter so that the unusual localization / threading behavior can be + // reused. + return new TimeFormatter().formatMillisWithFixedFormat(timeMillis); + } +} diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index 5a9ab3811498..6aef5a5cf2a5 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -40,6 +40,7 @@ public class FeatureFlagUtils { public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid"; public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press"; public static final String DYNAMIC_SYSTEM = "settings_dynamic_system"; + public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2"; private static final Map<String, String> DEFAULT_FLAGS; @@ -56,6 +57,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false"); DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false"); DEFAULT_FLAGS.put("settings_skip_direction_mutable", "true"); + DEFAULT_FLAGS.put(SETTINGS_WIFITRACKER2, "false"); } /** diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl index 956161acd762..955be8d40c47 100644 --- a/core/java/android/view/IRecentsAnimationController.aidl +++ b/core/java/android/view/IRecentsAnimationController.aidl @@ -77,6 +77,21 @@ interface IRecentsAnimationController { void hideCurrentInputMethod(); /** + * This call is deprecated, use #setDeferCancelUntilNextTransition() instead + * TODO(138144750): Remove this method once there are no callers + * @deprecated + */ + void setCancelWithDeferredScreenshot(boolean screenshot); + + /** + * Clean up the screenshot of previous task which was created during recents animation that + * was cancelled by a stack order change. + * + * @see {@link IRecentsAnimationRunner#onAnimationCanceled} + */ + void cleanupScreenshot(); + + /** * Set a state for controller whether would like to cancel recents animations with deferred * task screenshot presentation. * @@ -86,22 +101,23 @@ interface IRecentsAnimationController { * screenshot, so that Launcher can still control the leash lifecycle & make the next app * transition animate smoothly without flickering. * - * @param screenshot When set {@code true}, means recents animation will be canceled when the - * next app launch. System will take previous task's screenshot when the next - * app transition starting, and skip previous task's animation. - * Set {@code false} means will not take screenshot & skip animation - * for previous task. + * @param defer When set {@code true}, means that the recents animation will defer canceling the + * animation when a stack order change is triggered until the subsequent app + * transition start and skip previous task's animation. + * When set to {@code false}, means that the recents animation will be canceled + * immediately when the stack order changes. + * @param screenshot When set {@code true}, means that the system will take previous task's + * screenshot and replace the contents of the leash with it when the next app + * transition starting. The runner must call #cleanupScreenshot() to end the + * recents animation. + * When set to {@code false}, means that the system will simply wait for the + * next app transition start to immediately cancel the recents animation. This + * can be useful when you want an immediate transition into a state where the + * task is shown in the home/recents activity (without waiting for a + * screenshot). * * @see #cleanupScreenshot() * @see IRecentsAnimationRunner#onCancelled */ - void setCancelWithDeferredScreenshot(boolean screenshot); - - /** - * Clean up the screenshot of previous task which was created during recents animation that - * was cancelled by a stack order change. - * - * @see {@link IRecentsAnimationRunner#onAnimationCanceled} - */ - void cleanupScreenshot(); + void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot); } diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl index 9c652a8d990b..6cda60c80b7d 100644 --- a/core/java/android/view/IRecentsAnimationRunner.aidl +++ b/core/java/android/view/IRecentsAnimationRunner.aidl @@ -36,7 +36,7 @@ oneway interface IRecentsAnimationRunner { * @param deferredWithScreenshot If set to {@code true}, the contents of the task will be * replaced with a screenshot, such that the runner's leash is * still active. As soon as the runner doesn't need the leash - * anymore, it can call + * anymore, it must call * {@link IRecentsAnimationController#cleanupScreenshot). * * @see {@link RecentsAnimationController#cleanupScreenshot} diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 9cc6b287431e..1a6689838545 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -96,7 +96,7 @@ import java.util.concurrent.locks.ReentrantLock; * artifacts may occur on previous versions of the platform when its window is * positioned asynchronously.</p> */ -public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback { +public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback { private static final String TAG = "SurfaceView"; private static final boolean DEBUG = false; private static final boolean DEBUG_POSITION = false; @@ -227,9 +227,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mRequestedVisible = mViewVisibility && mWindowVisibility && !mWindowStopped; } - /** @hide */ - @Override - public void windowStopped(boolean stopped) { + private void setWindowStopped(boolean stopped) { mWindowStopped = stopped; updateRequestedVisibility(); updateSurface(); @@ -239,7 +237,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb protected void onAttachedToWindow() { super.onAttachedToWindow(); - getViewRootImpl().addWindowStoppedCallback(this); + getViewRootImpl().addSurfaceChangedCallback(this); mWindowStopped = false; mViewVisibility = getVisibility() == VISIBLE; @@ -459,7 +457,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb // the lifecycle. Instead of attaching it to a view, he/she can just pass // the SurfaceHolder forward, most live wallpapers do it. if (viewRoot != null) { - viewRoot.removeWindowStoppedCallback(this); + viewRoot.removeSurfaceChangedCallback(this); } mAttachedToWindow = false; @@ -1349,4 +1347,33 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb public SurfaceControl getSurfaceControl() { return mSurfaceControl; } + + /** + * Set window stopped to false and update surface visibility when ViewRootImpl surface is + * created. + * @hide + */ + @Override + public void surfaceCreated(SurfaceControl.Transaction t) { + setWindowStopped(false); + } + + /** + * Set window stopped to true and update surface visibility when ViewRootImpl surface is + * destroyed. + * @hide + */ + @Override + public void surfaceDestroyed() { + setWindowStopped(true); + } + + /** + * Called when a valid ViewRootImpl surface is replaced by another valid surface. + * @hide + */ + @Override + public void surfaceReplaced(SurfaceControl.Transaction t) { + + } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 69884dc62fb3..45309bb272cf 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -967,6 +967,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static boolean sBrokenInsetsDispatch; + /** + * Prior to Q, calling + * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} + * did not call update the window format so the opacity of the background was not correctly + * applied to the window. Some applications rely on this misbehavior to work properly. + * <p> + * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is + * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)} + * which updates the window format. + * @hide + */ + protected static boolean sBrokenWindowBackground; + /** @hide */ @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO}) @Retention(RetentionPolicy.SOURCE) @@ -5208,6 +5221,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL || targetSdkVersion < Build.VERSION_CODES.Q; + sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q; + sCompatibilityDone = true; } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 613ddcf577ed..354cc9645635 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -478,6 +478,12 @@ public final class ViewRootImpl implements ViewParent, private final SurfaceControl mSurfaceControl = new SurfaceControl(); /** + * Transaction object that can be used to synchronize child SurfaceControl changes with + * ViewRootImpl SurfaceControl changes by the server. The object is passed along with + * the SurfaceChangedCallback. + */ + private final Transaction mSurfaceChangedTransaction = new Transaction(); + /** * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds * are set to the parent's bounds adjusted for surface insets. This surface is created when * {@link ViewRootImpl#createBoundsSurface(int)} is called. @@ -1541,19 +1547,6 @@ public final class ViewRootImpl implements ViewParent, mIsAmbientMode = ambient; } - interface WindowStoppedCallback { - public void windowStopped(boolean stopped); - } - private final ArrayList<WindowStoppedCallback> mWindowStoppedCallbacks = new ArrayList<>(); - - void addWindowStoppedCallback(WindowStoppedCallback c) { - mWindowStoppedCallbacks.add(c); - } - - void removeWindowStoppedCallback(WindowStoppedCallback c) { - mWindowStoppedCallbacks.remove(c); - } - void setWindowStopped(boolean stopped) { checkThread(); if (mStopped != stopped) { @@ -1570,14 +1563,11 @@ public final class ViewRootImpl implements ViewParent, if (renderer != null) { renderer.destroyHardwareResources(mView); } - } - - for (int i = 0; i < mWindowStoppedCallbacks.size(); i++) { - mWindowStoppedCallbacks.get(i).windowStopped(stopped); - } - if (mStopped) { - if (mSurfaceHolder != null && mSurface.isValid()) { + if (mSurface.isValid()) { + if (mSurfaceHolder != null) { + notifyHolderSurfaceDestroyed(); + } notifySurfaceDestroyed(); } destroySurface(); @@ -1585,6 +1575,46 @@ public final class ViewRootImpl implements ViewParent, } } + /** Register callbacks to be notified when the ViewRootImpl surface changes. */ + interface SurfaceChangedCallback { + void surfaceCreated(Transaction t); + void surfaceReplaced(Transaction t); + void surfaceDestroyed(); + } + + private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>(); + void addSurfaceChangedCallback(SurfaceChangedCallback c) { + mSurfaceChangedCallbacks.add(c); + } + + void removeSurfaceChangedCallback(SurfaceChangedCallback c) { + mSurfaceChangedCallbacks.remove(c); + } + + private void notifySurfaceCreated() { + for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) { + mSurfaceChangedCallbacks.get(i).surfaceCreated(mSurfaceChangedTransaction); + } + } + + /** + * Notify listeners when the ViewRootImpl surface has been replaced. This callback will not be + * called if a new surface is created, only if the valid surface has been replaced with another + * valid surface. + */ + private void notifySurfaceReplaced() { + for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) { + mSurfaceChangedCallbacks.get(i).surfaceReplaced(mSurfaceChangedTransaction); + } + } + + private void notifySurfaceDestroyed() { + for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) { + mSurfaceChangedCallbacks.get(i).surfaceDestroyed(); + } + } + + /** * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and * crop bounds set to the parent's bounds adjusted for surface insets. @@ -1984,7 +2014,7 @@ public final class ViewRootImpl implements ViewParent, mIsInTraversal = true; mWillDrawSoon = true; boolean windowSizeMayChange = false; - boolean surfaceChanged = false; + final boolean windowAttributesChanged = mWindowAttributesChanged; WindowManager.LayoutParams lp = mWindowAttributes; int desiredWindowWidth; @@ -2003,7 +2033,6 @@ public final class ViewRootImpl implements ViewParent, WindowManager.LayoutParams params = null; if (mWindowAttributesChanged) { mWindowAttributesChanged = false; - surfaceChanged = true; params = lp; } CompatibilityInfo compatibilityInfo = @@ -2244,6 +2273,10 @@ public final class ViewRootImpl implements ViewParent, final boolean isViewVisible = viewVisibility == View.VISIBLE; final boolean windowRelayoutWasForced = mForceNextWindowRelayout; boolean surfaceSizeChanged = false; + boolean surfaceCreated = false; + boolean surfaceDestroyed = false; + /* True if surface generation id changes. */ + boolean surfaceReplaced = false; if (mFirst || windowShouldResize || insetsChanged || viewVisibilityChanged || params != null || mForceNextWindowRelayout) { @@ -2325,10 +2358,14 @@ public final class ViewRootImpl implements ViewParent, final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets); surfaceSizeChanged = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0; - surfaceChanged |= surfaceSizeChanged; final boolean alwaysConsumeSystemBarsChanged = mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars; final boolean colorModeChanged = hasColorModeChanged(lp.getColorMode()); + surfaceCreated = !hadSurface && mSurface.isValid(); + surfaceDestroyed = hadSurface && !mSurface.isValid(); + surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId()) + && mSurface.isValid(); + if (contentInsetsChanged) { mAttachInfo.mContentInsets.set(mPendingContentInsets); if (DEBUG_LAYOUT) Log.v(mTag, "Content insets changing to: " @@ -2383,33 +2420,32 @@ public final class ViewRootImpl implements ViewParent, lp.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT); } - if (!hadSurface) { - if (mSurface.isValid()) { - // If we are creating a new surface, then we need to - // completely redraw it. - mFullRedrawNeeded = true; - mPreviousTransparentRegion.setEmpty(); + if (surfaceCreated) { + // If we are creating a new surface, then we need to + // completely redraw it. + mFullRedrawNeeded = true; + mPreviousTransparentRegion.setEmpty(); - // Only initialize up-front if transparent regions are not - // requested, otherwise defer to see if the entire window - // will be transparent - if (mAttachInfo.mThreadedRenderer != null) { - try { - hwInitialized = mAttachInfo.mThreadedRenderer.initialize( - mSurface); - if (hwInitialized && (host.mPrivateFlags - & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) { - // Don't pre-allocate if transparent regions - // are requested as they may not be needed - mAttachInfo.mThreadedRenderer.allocateBuffers(); - } - } catch (OutOfResourcesException e) { - handleOutOfResourcesException(e); - return; + // Only initialize up-front if transparent regions are not + // requested, otherwise defer to see if the entire window + // will be transparent + if (mAttachInfo.mThreadedRenderer != null) { + try { + hwInitialized = mAttachInfo.mThreadedRenderer.initialize( + mSurface); + if (hwInitialized && (host.mPrivateFlags + & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) { + // Don't pre-allocate if transparent regions + // are requested as they may not be needed + mAttachInfo.mThreadedRenderer.allocateBuffers(); } + } catch (OutOfResourcesException e) { + handleOutOfResourcesException(e); + return; } } - } else if (!mSurface.isValid()) { + notifySurfaceCreated(); + } else if (surfaceDestroyed) { // If the surface has been removed, then reset the scroll // positions. if (mLastScrolledFocus != null) { @@ -2427,10 +2463,12 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mThreadedRenderer.isEnabled()) { mAttachInfo.mThreadedRenderer.destroy(); } - } else if ((surfaceGenerationId != mSurface.getGenerationId() + notifySurfaceDestroyed(); + } else if ((surfaceReplaced || surfaceSizeChanged || windowRelayoutWasForced || colorModeChanged) && mSurfaceHolder == null - && mAttachInfo.mThreadedRenderer != null) { + && mAttachInfo.mThreadedRenderer != null + && mSurface.isValid()) { mFullRedrawNeeded = true; try { // Need to do updateSurface (which leads to CanvasContext::setSurface and @@ -2448,6 +2486,10 @@ public final class ViewRootImpl implements ViewParent, } } + if (!surfaceCreated && surfaceReplaced) { + notifySurfaceReplaced(); + } + final boolean freeformResizing = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM) != 0; final boolean dockedResizing = (relayoutResult @@ -2503,31 +2545,32 @@ public final class ViewRootImpl implements ViewParent, } mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight); mSurfaceHolder.mSurfaceLock.unlock(); - if (mSurface.isValid()) { - if (!hadSurface) { - mSurfaceHolder.ungetCallbacks(); - - mIsCreating = true; - SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); - if (callbacks != null) { - for (SurfaceHolder.Callback c : callbacks) { - c.surfaceCreated(mSurfaceHolder); - } + if (surfaceCreated) { + mSurfaceHolder.ungetCallbacks(); + + mIsCreating = true; + SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks(); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceCreated(mSurfaceHolder); } - surfaceChanged = true; } - if (surfaceChanged || surfaceGenerationId != mSurface.getGenerationId()) { - SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); - if (callbacks != null) { - for (SurfaceHolder.Callback c : callbacks) { - c.surfaceChanged(mSurfaceHolder, lp.format, - mWidth, mHeight); - } + } + + if ((surfaceCreated || surfaceReplaced || surfaceSizeChanged + || windowAttributesChanged) && mSurface.isValid()) { + SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks(); + if (callbacks != null) { + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceChanged(mSurfaceHolder, lp.format, + mWidth, mHeight); } } mIsCreating = false; - } else if (hadSurface) { - notifySurfaceDestroyed(); + } + + if (surfaceDestroyed) { + notifyHolderSurfaceDestroyed(); mSurfaceHolder.mSurfaceLock.lock(); try { mSurfaceHolder.mSurface = new Surface(); @@ -2841,7 +2884,7 @@ public final class ViewRootImpl implements ViewParent, } } - private void notifySurfaceDestroyed() { + private void notifyHolderSurfaceDestroyed() { mSurfaceHolder.ungetCallbacks(); SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks(); if (callbacks != null) { @@ -3447,7 +3490,7 @@ public final class ViewRootImpl implements ViewParent, private void reportDrawFinished() { try { mDrawsNeededToReport = 0; - mWindowSession.finishDrawing(mWindow, null /* postDrawTransaction */); + mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction); } catch (RemoteException e) { // Have fun! } diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index efd5daf0b455..a428feac8806 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -921,10 +921,12 @@ public class NumberPicker extends LinearLayout { if (!mFlingScroller.isFinished()) { mFlingScroller.forceFinished(true); mAdjustScroller.forceFinished(true); + onScrollerFinished(mFlingScroller); onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); } else if (!mAdjustScroller.isFinished()) { mFlingScroller.forceFinished(true); mAdjustScroller.forceFinished(true); + onScrollerFinished(mAdjustScroller); } else if (mLastDownEventY < mTopSelectionDividerTop) { postChangeCurrentByOneFromLongPress( false, ViewConfiguration.getLongPressTimeout()); @@ -2556,14 +2558,16 @@ public class NumberPicker extends LinearLayout { } return false; } - case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: + case R.id.accessibilityActionScrollDown: { if (NumberPicker.this.isEnabled() && (getWrapSelectorWheel() || getValue() < getMaxValue())) { changeValueByOne(true); return true; } } return false; - case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: + case R.id.accessibilityActionScrollUp: { if (NumberPicker.this.isEnabled() && (getWrapSelectorWheel() || getValue() > getMinValue())) { changeValueByOne(false); @@ -2865,10 +2869,13 @@ public class NumberPicker extends LinearLayout { } if (NumberPicker.this.isEnabled()) { if (getWrapSelectorWheel() || getValue() < getMaxValue()) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_DOWN); } if (getWrapSelectorWheel() || getValue() > getMinValue()) { - info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + info.addAction( + AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD); + info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP); } } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index d985528c38fb..6b324a541c42 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -1202,13 +1202,13 @@ public class RelativeLayout extends ViewGroup { * determine where to position the view on the screen. If the view is not contained * within a relative layout, these attributes are ignored. * - * See the <a href="/guide/topics/ui/layout/relative.html"> - * Relative Layout</a> guide for example code demonstrating how to use relative layout’s + * See the <a href="{@docRoot}guide/topics/ui/layout/relative.html">Relative + * Layout</a> guide for example code demonstrating how to use relative layout's * layout parameters in a layout XML. * * To learn more about layout parameters and how they differ from typical view attributes, - * see the <a href="/guide/topics/ui/declaring-layout.html#attributes"> - * Layouts guide</a>. + * see the <a href="{@docRoot}guide/topics/ui/declaring-layout.html#attributes">Layouts + * guide</a>. * * * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignWithParentIfMissing diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index 49a0f39b3bad..4c67b080252a 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -433,7 +433,7 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { * to the next tabbed view, in this example). * <p> * To move both the focus AND the selected tab at once, please use - * {@link #setCurrentTab}. Normally, the view logic takes care of + * {@link #focusCurrentTab}. Normally, the view logic takes care of * adjusting the focus, so unless you're circumventing the UI, * you'll probably just focus your interest here. * diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java index 80ea363a6ad6..d36f3434e8c8 100644 --- a/core/java/android/widget/ViewAnimator.java +++ b/core/java/android/widget/ViewAnimator.java @@ -57,6 +57,9 @@ public class ViewAnimator extends FrameLayout { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewAnimator); + saveAttributeDataForStyleable(context, com.android.internal.R.styleable.ViewAnimator, + attrs, a, 0, 0); + int resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_inAnimation, 0); if (resource > 0) { setInAnimation(context, resource); @@ -90,6 +93,8 @@ public class ViewAnimator extends FrameLayout { // attribute to override. final TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout); + saveAttributeDataForStyleable(context, com.android.internal.R.styleable.FrameLayout, + attrs, a, 0, 0); final boolean measureAllChildren = a.getBoolean( com.android.internal.R.styleable.FrameLayout_measureAllChildren, true); setMeasureAllChildren(measureAllChildren); diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java index 3ac58e018a45..d53fadacb609 100644 --- a/core/java/com/android/internal/os/KernelWakelockReader.java +++ b/core/java/com/android/internal/os/KernelWakelockReader.java @@ -27,6 +27,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; +import java.io.File; import java.io.FileInputStream; import java.util.Iterator; @@ -38,6 +39,7 @@ public class KernelWakelockReader { private static int sKernelWakelockUpdateVersion = 0; private static final String sWakelockFile = "/proc/wakelocks"; private static final String sWakeupSourceFile = "/d/wakeup_sources"; + private static final String sSysClassWakeupDir = "/sys/class/wakeup"; private static final int[] PROC_WAKELOCKS_FORMAT = new int[] { Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name @@ -71,99 +73,108 @@ public class KernelWakelockReader { * @return the updated data. */ public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) { - byte[] buffer = new byte[32*1024]; - int len = 0; - boolean wakeup_sources; - final long startTime = SystemClock.uptimeMillis(); + boolean useSystemSuspend = (new File(sSysClassWakeupDir)).exists(); - final int oldMask = StrictMode.allowThreadDiskReadsMask(); - try { - FileInputStream is; - try { - is = new FileInputStream(sWakelockFile); - wakeup_sources = false; - } catch (java.io.FileNotFoundException e) { + if (useSystemSuspend) { + WakeLockInfo[] wlStats = null; + if (mSuspendControlService == null) { try { - is = new FileInputStream(sWakeupSourceFile); - wakeup_sources = true; - } catch (java.io.FileNotFoundException e2) { - Slog.wtf(TAG, "neither " + sWakelockFile + " nor " + - sWakeupSourceFile + " exists"); + mSuspendControlService = ISuspendControlService.Stub.asInterface( + ServiceManager.getServiceOrThrow("suspend_control")); + } catch (ServiceNotFoundException e) { + Slog.wtf(TAG, "Required service suspend_control not available", e); return null; } } - int cnt; - while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) { - len += cnt; + try { + wlStats = mSuspendControlService.getWakeLockStats(); + updateVersion(staleStats); + updateWakelockStats(wlStats, staleStats); + } catch (RemoteException e) { + Slog.wtf(TAG, "Failed to obtain wakelock stats from ISuspendControlService", e); + return null; } - is.close(); - } catch (java.io.IOException e) { - Slog.wtf(TAG, "failed to read kernel wakelocks", e); - return null; - } finally { - StrictMode.setThreadPolicyMask(oldMask); - } + return removeOldStats(staleStats); - final long readTime = SystemClock.uptimeMillis() - startTime; - if (readTime > 100) { - Slog.w(TAG, "Reading wakelock stats took " + readTime + "ms"); - } + } else { + byte[] buffer = new byte[32*1024]; + int len = 0; + boolean wakeup_sources; + final long startTime = SystemClock.uptimeMillis(); - if (len > 0) { - if (len >= buffer.length) { - Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length); - } - int i; - for (i=0; i<len; i++) { - if (buffer[i] == '\0') { - len = i; - break; + final int oldMask = StrictMode.allowThreadDiskReadsMask(); + try { + FileInputStream is; + try { + is = new FileInputStream(sWakelockFile); + wakeup_sources = false; + } catch (java.io.FileNotFoundException e) { + try { + is = new FileInputStream(sWakeupSourceFile); + wakeup_sources = true; + } catch (java.io.FileNotFoundException e2) { + Slog.wtf(TAG, "neither " + sWakelockFile + " nor " + + sWakeupSourceFile + " exists"); + return null; + } } - } - } - updateVersion(staleStats); + int cnt; + while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) { + len += cnt; + } - parseProcWakelocks(buffer, len, wakeup_sources, staleStats); + is.close(); + } catch (java.io.IOException e) { + Slog.wtf(TAG, "failed to read kernel wakelocks", e); + return null; + } finally { + StrictMode.setThreadPolicyMask(oldMask); + } - if (mSuspendControlService == null) { - try { - mSuspendControlService = ISuspendControlService.Stub.asInterface( - ServiceManager.getServiceOrThrow("suspend_control")); - } catch (ServiceNotFoundException e) { - Slog.wtf(TAG, "Required service suspend_control not available", e); + final long readTime = SystemClock.uptimeMillis() - startTime; + if (readTime > 100) { + Slog.w(TAG, "Reading wakelock stats took " + readTime + "ms"); } - } - try { - WakeLockInfo[] wlStats = mSuspendControlService.getWakeLockStats(); - getNativeWakelockStats(wlStats, staleStats); - } catch (RemoteException e) { - Slog.wtf(TAG, "Failed to obtain wakelock stats from ISuspendControlService", e); - } + if (len > 0) { + if (len >= buffer.length) { + Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length); + } + int i; + for (i=0; i<len; i++) { + if (buffer[i] == '\0') { + len = i; + break; + } + } + } - return removeOldStats(staleStats); + updateVersion(staleStats); + parseProcWakelocks(buffer, len, wakeup_sources, staleStats); + return removeOldStats(staleStats); + } } /** - * Reads native wakelock stats from SystemSuspend and updates staleStats with the new - * information. + * Updates statleStats with stats from SystemSuspend. * @param staleStats Existing object to update. * @return the updated stats. */ @VisibleForTesting - public KernelWakelockStats getNativeWakelockStats(WakeLockInfo[] wlStats, + public KernelWakelockStats updateWakelockStats(WakeLockInfo[] wlStats, final KernelWakelockStats staleStats) { for (WakeLockInfo info : wlStats) { if (!staleStats.containsKey(info.name)) { staleStats.put(info.name, new KernelWakelockStats.Entry((int) info.activeCount, - info.totalTime, sKernelWakelockUpdateVersion)); + info.totalTime * 1000 /* ms to us */, sKernelWakelockUpdateVersion)); } else { KernelWakelockStats.Entry kwlStats = staleStats.get(info.name); kwlStats.mCount = (int) info.activeCount; - kwlStats.mTotalTime = info.totalTime; + // Convert milliseconds to microseconds + kwlStats.mTotalTime = info.totalTime * 1000; kwlStats.mVersion = sKernelWakelockUpdateVersion; } } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 599c354f0a1a..981d0bb1cd69 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -989,7 +989,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } else { mBackgroundPadding.setEmpty(); } - drawableChanged(); + if (!View.sBrokenWindowBackground) { + drawableChanged(); + } } } diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp index d29857d0cf12..d1b952130e88 100644 --- a/core/jni/android/graphics/Picture.cpp +++ b/core/jni/android/graphics/Picture.cpp @@ -100,8 +100,9 @@ void Picture::draw(Canvas* canvas) { this->endRecording(); SkASSERT(NULL != mPicture.get()); } - if (NULL != mPicture.get()) { - mPicture->playback(canvas->asSkCanvas()); + + if (mPicture) { + canvas->drawPicture(*mPicture); } } diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index c3e7a36bef78..13e1dfa00160 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -259,6 +259,8 @@ static void load_maps(int pid, stats_t* stats, bool* foundSwapPss) which_heap = HEAP_NATIVE; } else if (base::StartsWith(name, "[stack")) { which_heap = HEAP_STACK; + } else if (base::StartsWith(name, "[anon:stack_and_tls:")) { + which_heap = HEAP_STACK; } else if (base::EndsWith(name, ".so")) { which_heap = HEAP_SO; is_swappable = true; diff --git a/core/proto/OWNERS b/core/proto/OWNERS index a3d4798647be..71e386011253 100644 --- a/core/proto/OWNERS +++ b/core/proto/OWNERS @@ -7,7 +7,7 @@ yaochen@google.com yro@google.com # Settings UI -per-file settings_enums.proto=zhfan@google.com +per-file settings_enums.proto=tmfang@google.com # Frameworks ogunwale@google.com diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index c023438eecc2..3323095a6244 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2401,4 +2401,11 @@ enum PageId { // OS: Q // Note: Gear icon is shown next to gesture navigation preference and opens sensitivity dialog SETTINGS_GESTURE_NAV_BACK_SENSITIVITY_DLG = 1748; + + // ---- End Q Constants, all Q constants go above this line ---- + // OPEN: Settings > Network & Internet > Wi-Fi > Click new network + // CATEGORY: SETTINGS + // OS: R + SETTINGS_WIFI_CONFIGURE_NETWORK = 1800; + } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 40acebc40abd..aa440d348a57 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -727,7 +727,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.SEND_SMS" @@ -741,7 +741,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.RECEIVE_SMS" @@ -755,7 +755,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.READ_SMS" @@ -769,7 +769,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.RECEIVE_WAP_PUSH" @@ -783,7 +783,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.RECEIVE_MMS" @@ -806,7 +806,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. @hide Pending API council approval --> @@ -852,7 +852,7 @@ targetSdkVersion}</a> is 4 or higher. <p> This is a soft restricted permission which cannot be held by an app it its - full form until the installer on record did not whitelist the permission. + full form until the installer on record whitelists the permission. Specifically, if the permission is whitelisted the holder app can access external storage and the visual and aural media collections while if the permission is not whitelisted the holder app can only access to the visual @@ -860,7 +860,7 @@ meaning that the whitelist state can be specified only at install time and cannot change until the app is installed. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. - --> + <p>Protection level: dangerous --> <permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_sdcardRead" @@ -881,8 +881,9 @@ read/write files in your application-specific directories returned by {@link android.content.Context#getExternalFilesDir} and {@link android.content.Context#getExternalCacheDir}. - <p>Is this permission is not whitelisted for an app that targets an API level before + <p>If this permission is not whitelisted for an app that targets an API level before {@link android.os.Build.VERSION_CODES#Q} this permission cannot be granted to apps.</p> + <p>Protection level: dangerous</p> --> <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:permissionGroup="android.permission-group.UNDEFINED" @@ -892,7 +893,8 @@ android:protectionLevel="dangerous" /> <!-- Allows an application to access any geographic locations persisted in the - user's shared collection. --> + user's shared collection. + <p>Protection level: dangerous --> <permission android:name="android.permission.ACCESS_MEDIA_LOCATION" android:permissionGroup="android.permission-group.UNDEFINED" android:label="@string/permlab_mediaLocation" @@ -949,7 +951,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" @@ -995,7 +997,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.READ_CALL_LOG" @@ -1019,7 +1021,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. --> <permission android:name="android.permission.WRITE_CALL_LOG" @@ -1035,7 +1037,7 @@ <p>Protection level: dangerous <p> This is a hard restricted permission which cannot be held by an app until - the installer on record did not whitelist the permission. For more details see + the installer on record whitelists the permission. For more details see {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}. @deprecated Applications should use {@link android.telecom.CallRedirectionService} instead @@ -1694,7 +1696,7 @@ <!-- Allows applications to pair bluetooth devices without user interaction, and to allow or disallow phonebook access or message access. - This is not available to third party applications. --> + <p>Not for use by third-party applications. --> <permission android:name="android.permission.BLUETOOTH_PRIVILEGED" android:protectionLevel="signature|privileged" /> @@ -2544,7 +2546,8 @@ android:protectionLevel="signature" /> <!-- Allows an application to modify the current configuration, such - as locale. --> + as locale. + <p>Protection level: signature|privileged|development --> <permission android:name="android.permission.CHANGE_CONFIGURATION" android:protectionLevel="signature|privileged|development" /> @@ -2843,7 +2846,8 @@ <!-- ==================================== --> <eat-comment /> - <!-- Allows access to the list of accounts in the Accounts Service. --> + <!-- Allows access to the list of accounts in the Accounts Service. + <p>Protection level: signature|privileged --> <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED" android:protectionLevel="signature|privileged" /> @@ -3429,7 +3433,8 @@ android:protectionLevel="signature" /> <!-- Old permission for deleting an app's cache files, no longer used, - but signals for us to quietly ignore calls instead of throwing an exception. --> + but signals for us to quietly ignore calls instead of throwing an exception. + <p>Protection level: signature|privileged --> <permission android:name="android.permission.DELETE_CACHE_FILES" android:protectionLevel="signature|privileged" /> @@ -3792,7 +3797,8 @@ <!-- Allows an application to collect component usage statistics <p>Declaring the permission implies intention to use the API and the user of the - device can grant permission through the Settings application. --> + device can grant permission through the Settings application. + <p>Protection level: signature|privileged|development|appop --> <permission android:name="android.permission.PACKAGE_USAGE_STATS" android:protectionLevel="signature|privileged|development|appop" /> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> @@ -3815,14 +3821,14 @@ <!-- Permission an application must hold in order to use {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}. - This is a normal permission: an app requesting it will always be granted the - permission, without the user needing to approve or see it. --> + <p>Protection level: normal --> <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" android:label="@string/permlab_requestIgnoreBatteryOptimizations" android:description="@string/permdesc_requestIgnoreBatteryOptimizations" android:protectionLevel="normal" /> - <!-- Allows an application to collect battery statistics --> + <!-- Allows an application to collect battery statistics + <p>Protection level: signature|privileged|development --> <permission android:name="android.permission.BATTERY_STATS" android:protectionLevel="signature|privileged|development" /> @@ -3852,7 +3858,8 @@ android:protectionLevel="signature" /> <!-- Must be required by a {@link android.widget.RemoteViewsService}, - to ensure that only the system can bind to it. --> + to ensure that only the system can bind to it. + <p>Protection level: signature|privileged --> <permission android:name="android.permission.BIND_REMOTEVIEWS" android:protectionLevel="signature|privileged" /> @@ -3894,7 +3901,8 @@ to the path in the provider where global search queries are performed. This permission can not be held by regular applications; it is used by applications to protect themselves from everyone else - besides global search. --> + besides global search. + <p>Protection level: signature|privileged --> <permission android:name="android.permission.GLOBAL_SEARCH" android:protectionLevel="signature|privileged" /> @@ -4433,7 +4441,8 @@ <permission android:name="android.permission.MODIFY_THEME_OVERLAY" android:protectionLevel="signature" /> - <!-- Allows an instant app to create foreground services. --> + <!-- Allows an instant app to create foreground services. + <p>Protection level: signature|development|instant|appop --> <permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE" android:protectionLevel="signature|development|instant|appop" /> @@ -4503,7 +4512,8 @@ <permission android:name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" android:protectionLevel="signature|privileged" /> - <!-- A subclass of {@link android.service.carrier.CarrierMessagingClientService} must be protected with this permission. --> + <!-- A subclass of {@link android.service.carrier.CarrierMessagingClientService} must be protected with this permission. + <p>Protection level: signature --> <permission android:name="android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE" android:protectionLevel="signature" /> @@ -4535,13 +4545,15 @@ <permission android:name="android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS" android:protectionLevel="signature" /> - <!-- Allows financial apps to read filtered sms messages. --> + <!-- Allows financial apps to read filtered sms messages. + Protection level: signature|appop --> <permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS" android:protectionLevel="signature|appop" /> <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#Q} that want to use {@link android.app.Notification.Builder#setFullScreenIntent notification full screen - intents}. --> + intents}. + <p>Protection level: normal --> <permission android:name="android.permission.USE_FULL_SCREEN_INTENT" android:protectionLevel="normal" /> @@ -4598,6 +4610,7 @@ android:supportsRtl="true" android:theme="@style/Theme.DeviceDefault.Light.DarkActionBar" android:defaultToDeviceProtectedStorage="true" + android:forceQueryable="true" android:directBootAware="true"> <activity android:name="com.android.internal.app.ChooserActivity" android:theme="@style/Theme.DeviceDefault.Resolver" diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index be6cdcf3f098..3ea8a778ba9b 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1743,6 +1743,13 @@ - {@code true} for apps with targetSdkVersion < 29. --> <attr name="requestLegacyExternalStorage" format="boolean" /> + + <!-- If {@code true} this app declares that it should be visible to all other apps on + device, regardless of what they declare via the {@code queries} tags in their + manifest. + + The default value is {@code false}. --> + <attr name="forceQueryable" format="boolean" /> </declare-styleable> <!-- The <code>permission</code> tag declares a security permission that can be used to control access from other packages to specific components or @@ -1977,6 +1984,12 @@ <attr name="name" /> </declare-styleable> + <declare-styleable name="AndroidManifestQueries" parent="AndroidManifest" /> + <declare-styleable name="AndroidManifestQueriesPackage" parent="AndroidManifestQueries"> + <attr name="name" /> + </declare-styleable> + <declare-styleable name="AndroidManifestQueriesIntent" parent="AndroidManifestQueries" /> + <!-- The <code>static-library</code> tag declares that this apk is providing itself as a static shared library for other applications to use. Any app can declare such @@ -2477,6 +2490,7 @@ <!-- High dynamic range color mode. --> <enum name="hdr" value="2" /> </attr> + <attr name="forceQueryable" format="boolean" /> </declare-styleable> <!-- The <code>activity-alias</code> tag declares a new diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 3b1275354d1f..dce4bf3f1ed4 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1700,6 +1700,12 @@ <!-- Add packages here --> </string-array> + <string-array name="config_forceQueryablePackages" translatable="false"> + <item>com.android.settings</item> + <!-- Add packages here --> + </string-array> + + <!-- Component name of the default wallpaper. This will be ImageWallpaper if not specified --> <string name="default_wallpaper_component" translatable="false">@null</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index d91bbd006318..123deeb421b7 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -786,6 +786,7 @@ <java-symbol type="string" name="widget_default_class_name" /> <java-symbol type="string" name="emergency_calls_only" /> <java-symbol type="array" name="config_ephemeralResolverPackage" /> + <java-symbol type="array" name="config_forceQueryablePackages" /> <java-symbol type="string" name="eventTypeAnniversary" /> <java-symbol type="string" name="eventTypeBirthday" /> <java-symbol type="string" name="eventTypeCustom" /> diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java index b2254c5fe59e..eadf226b01ce 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java @@ -17,12 +17,10 @@ package com.android.server.broadcastradio.hal2; import static org.junit.Assert.*; -import android.hardware.broadcastradio.V2_0.ProgramInfo; import android.hardware.broadcastradio.V2_0.ProgramListChunk; import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; -import android.hardware.radio.RadioMetadata; import android.test.suitebuilder.annotation.MediumTest; import androidx.test.runner.AndroidJUnit4; @@ -30,7 +28,6 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -45,55 +42,58 @@ public class ProgramInfoCacheTest { private final ProgramSelector.Identifier mAmFmIdentifier = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, 88500); - private final RadioManager.ProgramInfo mAmFmInfo = makeProgramInfo( + private final RadioManager.ProgramInfo mAmFmInfo = TestUtils.makeProgramInfo( ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 0); private final ProgramSelector.Identifier mRdsIdentifier = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, 15019); - private final RadioManager.ProgramInfo mRdsInfo = makeProgramInfo( + private final RadioManager.ProgramInfo mRdsInfo = TestUtils.makeProgramInfo( ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 0); private final ProgramSelector.Identifier mDabEnsembleIdentifier = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, 1337); - private final RadioManager.ProgramInfo mDabEnsembleInfo = makeProgramInfo( + private final RadioManager.ProgramInfo mDabEnsembleInfo = TestUtils.makeProgramInfo( ProgramSelector.PROGRAM_TYPE_DAB, mDabEnsembleIdentifier, 0); private final ProgramSelector.Identifier mVendorCustomIdentifier = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_VENDOR_START, 9001); - private final RadioManager.ProgramInfo mVendorCustomInfo = makeProgramInfo( + private final RadioManager.ProgramInfo mVendorCustomInfo = TestUtils.makeProgramInfo( ProgramSelector.PROGRAM_TYPE_VENDOR_START, mVendorCustomIdentifier, 0); // HAL-side ProgramInfoCache containing all of the above ProgramInfos. - private final ProgramInfoCache mAllProgramInfos = new ProgramInfoCache(null, mAmFmInfo, + private final ProgramInfoCache mAllProgramInfos = new ProgramInfoCache(null, true, mAmFmInfo, mRdsInfo, mDabEnsembleInfo, mVendorCustomInfo); @Test public void testUpdateFromHal() { - // First test a purging chunk. - ProgramInfoCache cache = new ProgramInfoCache(null, mAmFmInfo); + // First test updating an incomplete cache with a purging, complete chunk. + ProgramInfoCache cache = new ProgramInfoCache(null, false, mAmFmInfo); ProgramListChunk chunk = new ProgramListChunk(); chunk.purge = true; - chunk.modified.add(programInfoToHal(mRdsInfo)); - chunk.modified.add(programInfoToHal(mDabEnsembleInfo)); - cache.updateFromHalProgramListChunk(chunk); chunk.complete = true; + chunk.modified.add(TestUtils.programInfoToHal(mRdsInfo)); + chunk.modified.add(TestUtils.programInfoToHal(mDabEnsembleInfo)); + cache.updateFromHalProgramListChunk(chunk); assertTrue(cache.programInfosAreExactly(mRdsInfo, mDabEnsembleInfo)); + assertTrue(cache.isComplete()); - // Then test a non-purging chunk. + // Then test a non-purging, incomplete chunk. chunk.purge = false; + chunk.complete = false; chunk.modified.clear(); - RadioManager.ProgramInfo updatedRdsInfo = makeProgramInfo(ProgramSelector.PROGRAM_TYPE_FM, - mRdsIdentifier, 1); - chunk.modified.add(programInfoToHal(updatedRdsInfo)); - chunk.modified.add(programInfoToHal(mVendorCustomInfo)); + RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 1); + chunk.modified.add(TestUtils.programInfoToHal(updatedRdsInfo)); + chunk.modified.add(TestUtils.programInfoToHal(mVendorCustomInfo)); chunk.removed.add(Convert.programIdentifierToHal(mDabEnsembleIdentifier)); cache.updateFromHalProgramListChunk(chunk); assertTrue(cache.programInfosAreExactly(updatedRdsInfo, mVendorCustomInfo)); + assertFalse(cache.isComplete()); } @Test public void testNullFilter() { - ProgramInfoCache cache = new ProgramInfoCache(null); + ProgramInfoCache cache = new ProgramInfoCache(null, true); cache.filterAndUpdateFrom(mAllProgramInfos, false); assertTrue(cache.programInfosAreExactly(mAmFmInfo, mRdsInfo, mDabEnsembleInfo, mVendorCustomInfo)); @@ -140,11 +140,11 @@ public class ProgramInfoCacheTest { @Test public void testPurgeUpdateChunks() { - ProgramInfoCache cache = new ProgramInfoCache(null, mAmFmInfo); + ProgramInfoCache cache = new ProgramInfoCache(null, false, mAmFmInfo); List<ProgramList.Chunk> chunks = cache.filterAndUpdateFromInternal(mAllProgramInfos, true, 3, 3); assertEquals(2, chunks.size()); - verifyChunkListFlags(chunks, true); + verifyChunkListFlags(chunks, true, true); verifyChunkListModified(chunks, 3, mAmFmInfo, mRdsInfo, mDabEnsembleInfo, mVendorCustomInfo); verifyChunkListRemoved(chunks, 0); @@ -154,23 +154,26 @@ public class ProgramInfoCacheTest { public void testDeltaUpdateChunksModificationsIncluded() { // Create a cache with a filter that allows modifications, and set its contents to // mAmFmInfo, mRdsInfo, mDabEnsembleInfo, and mVendorCustomInfo. - ProgramInfoCache cache = new ProgramInfoCache(null, mAmFmInfo, mRdsInfo, mDabEnsembleInfo, - mVendorCustomInfo); + ProgramInfoCache cache = new ProgramInfoCache(null, true, mAmFmInfo, mRdsInfo, + mDabEnsembleInfo, mVendorCustomInfo); // Create a HAL cache that: + // - Is complete. // - Retains mAmFmInfo. // - Replaces mRdsInfo with updatedRdsInfo. // - Drops mDabEnsembleInfo and mVendorCustomInfo. // - Introduces a new SXM info. - RadioManager.ProgramInfo updatedRdsInfo = makeProgramInfo(ProgramSelector.PROGRAM_TYPE_FM, - mRdsIdentifier, 1); - RadioManager.ProgramInfo newSxmInfo = makeProgramInfo(ProgramSelector.PROGRAM_TYPE_SXM, + RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 1); + RadioManager.ProgramInfo newSxmInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_SXM, new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_SXM_CHANNEL, 12345), 0); - ProgramInfoCache halCache = new ProgramInfoCache(null, mAmFmInfo, updatedRdsInfo, + ProgramInfoCache halCache = new ProgramInfoCache(null, true, mAmFmInfo, updatedRdsInfo, newSxmInfo); // Update the cache and verify: + // - The final chunk's complete flag is set. // - mAmFmInfo is retained and not reported in the chunks. // - updatedRdsInfo should appear as an update to mRdsInfo. // - newSxmInfo should appear as a new entry. @@ -178,7 +181,7 @@ public class ProgramInfoCacheTest { List<ProgramList.Chunk> chunks = cache.filterAndUpdateFromInternal(halCache, false, 5, 1); assertTrue(cache.programInfosAreExactly(mAmFmInfo, updatedRdsInfo, newSxmInfo)); assertEquals(2, chunks.size()); - verifyChunkListFlags(chunks, false); + verifyChunkListFlags(chunks, false, true); verifyChunkListModified(chunks, 5, updatedRdsInfo, newSxmInfo); verifyChunkListRemoved(chunks, 1, mDabEnsembleIdentifier, mVendorCustomIdentifier); } @@ -188,63 +191,50 @@ public class ProgramInfoCacheTest { // Create a cache with a filter that excludes modifications, and set its contents to // mAmFmInfo, mRdsInfo, mDabEnsembleInfo, and mVendorCustomInfo. ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new HashSet<Integer>(), - new HashSet<ProgramSelector.Identifier>(), true, true), mAmFmInfo, mRdsInfo, + new HashSet<ProgramSelector.Identifier>(), true, true), true, mAmFmInfo, mRdsInfo, mDabEnsembleInfo, mVendorCustomInfo); // Create a HAL cache that: + // - Is incomplete. // - Retains mAmFmInfo. // - Replaces mRdsInfo with updatedRdsInfo. // - Drops mDabEnsembleInfo and mVendorCustomInfo. // - Introduces a new SXM info. - RadioManager.ProgramInfo updatedRdsInfo = makeProgramInfo(ProgramSelector.PROGRAM_TYPE_FM, - mRdsIdentifier, 1); - RadioManager.ProgramInfo newSxmInfo = makeProgramInfo(ProgramSelector.PROGRAM_TYPE_SXM, + RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 1); + RadioManager.ProgramInfo newSxmInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_SXM, new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_SXM_CHANNEL, 12345), 0); - ProgramInfoCache halCache = new ProgramInfoCache(null, mAmFmInfo, updatedRdsInfo, + ProgramInfoCache halCache = new ProgramInfoCache(null, false, mAmFmInfo, updatedRdsInfo, newSxmInfo); // Update the cache and verify: + // - All complete flags are false. // - mAmFmInfo and mRdsInfo are retained and not reported in the chunks. // - newSxmInfo should appear as a new entry. // - mDabEnsembleInfo and mVendorCustomInfo should be reported as removed. List<ProgramList.Chunk> chunks = cache.filterAndUpdateFromInternal(halCache, false, 5, 1); assertTrue(cache.programInfosAreExactly(mAmFmInfo, mRdsInfo, newSxmInfo)); assertEquals(2, chunks.size()); - verifyChunkListFlags(chunks, false); + verifyChunkListFlags(chunks, false, false); verifyChunkListModified(chunks, 5, newSxmInfo); verifyChunkListRemoved(chunks, 1, mDabEnsembleIdentifier, mVendorCustomIdentifier); } - private static RadioManager.ProgramInfo makeProgramInfo(int programType, - ProgramSelector.Identifier identifier, int signalQuality) { - // Note: If you set new fields, check if programInfoToHal() needs to be updated as well. - return new RadioManager.ProgramInfo(new ProgramSelector(programType, identifier, null, - null), null, null, null, 0, signalQuality, new RadioMetadata.Builder().build(), - new HashMap<String, String>()); - } - - private static ProgramInfo programInfoToHal(RadioManager.ProgramInfo info) { - // Note that because Convert does not by design provide functions for all conversions, this - // function only copies fields that are set by makeProgramInfo(). - ProgramInfo hwInfo = new ProgramInfo(); - hwInfo.selector = Convert.programSelectorToHal(info.getSelector()); - hwInfo.signalQuality = info.getSignalStrength(); - return hwInfo; - } - // Verifies that: // - The first chunk's purge flag matches expectPurge. - // - The last chunk's complete flag is set. + // - The last chunk's complete flag matches expectComplete. // - All other flags are false. - private static void verifyChunkListFlags(List<ProgramList.Chunk> chunks, boolean expectPurge) { + private static void verifyChunkListFlags(List<ProgramList.Chunk> chunks, boolean expectPurge, + boolean expectComplete) { if (chunks.isEmpty()) { return; } for (int i = 0; i < chunks.size(); i++) { ProgramList.Chunk chunk = chunks.get(i); assertEquals(i == 0 && expectPurge, chunk.isPurge()); - assertEquals(i == chunks.size() - 1, chunk.isComplete()); + assertEquals(i == chunks.size() - 1 && expectComplete, chunk.isComplete()); } } diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java new file mode 100644 index 000000000000..f9e37981fa6f --- /dev/null +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.broadcastradio.hal2; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.hardware.broadcastradio.V2_0.IBroadcastRadio; +import android.hardware.broadcastradio.V2_0.ITunerCallback; +import android.hardware.broadcastradio.V2_0.ITunerSession; +import android.hardware.broadcastradio.V2_0.ProgramFilter; +import android.hardware.broadcastradio.V2_0.ProgramListChunk; +import android.hardware.broadcastradio.V2_0.Result; +import android.hardware.radio.ProgramList; +import android.hardware.radio.ProgramSelector; +import android.hardware.radio.RadioManager; +import android.os.RemoteException; +import android.test.suitebuilder.annotation.MediumTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Tests for v2 HAL RadioModule. + */ +@RunWith(AndroidJUnit4.class) +@MediumTest +public class StartProgramListUpdatesFanoutTest { + private static final String TAG = "BroadcastRadioTests.hal2.StartProgramListUpdatesFanout"; + + // Mocks + @Mock IBroadcastRadio mBroadcastRadioMock; + @Mock ITunerSession mHalTunerSessionMock; + private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks; + + // RadioModule under test + private RadioModule mRadioModule; + + // Objects created by mRadioModule + private ITunerCallback mHalTunerCallback; + private TunerSession[] mTunerSessions; + + // Data objects used during tests + private final ProgramSelector.Identifier mAmFmIdentifier = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, 88500); + private final RadioManager.ProgramInfo mAmFmInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 0); + private final RadioManager.ProgramInfo mModifiedAmFmInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 1); + + private final ProgramSelector.Identifier mRdsIdentifier = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, 15019); + private final RadioManager.ProgramInfo mRdsInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 0); + + private final ProgramSelector.Identifier mDabEnsembleIdentifier = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, 1337); + private final RadioManager.ProgramInfo mDabEnsembleInfo = TestUtils.makeProgramInfo( + ProgramSelector.PROGRAM_TYPE_DAB, mDabEnsembleIdentifier, 0); + + @Before + public void setup() throws RemoteException { + MockitoAnnotations.initMocks(this); + + mRadioModule = new RadioModule(mBroadcastRadioMock, new RadioManager.ModuleProperties(0, "", + 0, "", "", "", "", 0, 0, false, false, null, false, new int[] {}, new int[] {}, + null, null)); + + doAnswer((Answer) invocation -> { + mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0]; + IBroadcastRadio.openSessionCallback cb = (IBroadcastRadio.openSessionCallback) + invocation.getArguments()[1]; + cb.onValues(Result.OK, mHalTunerSessionMock); + return null; + }).when(mBroadcastRadioMock).openSession(any(), any()); + when(mHalTunerSessionMock.startProgramListUpdates(any())).thenReturn(Result.OK); + } + + @Test + public void testFanout() throws RemoteException { + // Open 3 clients that will all use the same filter, and start updates on two of them for + // now. The HAL TunerSession should only see 1 filter update. + openAidlClients(3); + ProgramList.Filter aidlFilter = new ProgramList.Filter(new HashSet<Integer>(), + new HashSet<ProgramSelector.Identifier>(), true, false); + ProgramFilter halFilter = Convert.programFilterToHal(aidlFilter); + for (int i = 0; i < 2; i++) { + mTunerSessions[i].startProgramListUpdates(aidlFilter); + } + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); + + // Initiate a program list update from the HAL side and verify both connected AIDL clients + // receive the update. + updateHalProgramInfo(true, Arrays.asList(mAmFmInfo, mRdsInfo), null); + for (int i = 0; i < 2; i++) { + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[i], true, Arrays.asList( + mAmFmInfo, mRdsInfo), null); + } + + // Repeat with a non-purging update. + updateHalProgramInfo(false, Arrays.asList(mModifiedAmFmInfo), + Arrays.asList(mRdsIdentifier)); + for (int i = 0; i < 2; i++) { + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[i], false, + Arrays.asList(mModifiedAmFmInfo), Arrays.asList(mRdsIdentifier)); + } + + // Now start updates on the 3rd client. Verify the HAL function has not been called again + // and client receives the appropriate update. + mTunerSessions[2].startProgramListUpdates(aidlFilter); + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(any()); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[2], true, + Arrays.asList(mModifiedAmFmInfo), null); + } + + @Test + public void testFiltering() throws RemoteException { + // Open 4 clients that will use the following filters: + // [0]: ID mRdsIdentifier, modifications excluded + // [1]: No categories, modifications excluded + // [2]: Type IDENTIFIER_TYPE_AMFM_FREQUENCY, modifications excluded + // [3]: Type IDENTIFIER_TYPE_AMFM_FREQUENCY, modifications included + openAidlClients(4); + ProgramList.Filter idFilter = new ProgramList.Filter(new HashSet<Integer>(), + new HashSet<ProgramSelector.Identifier>(Arrays.asList(mRdsIdentifier)), true, true); + ProgramList.Filter categoryFilter = new ProgramList.Filter(new HashSet<Integer>(), + new HashSet<ProgramSelector.Identifier>(), false, true); + ProgramList.Filter typeFilterWithoutModifications = new ProgramList.Filter( + new HashSet<Integer>(Arrays.asList(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY)), + new HashSet<ProgramSelector.Identifier>(), true, true); + ProgramList.Filter typeFilterWithModifications = new ProgramList.Filter( + new HashSet<Integer>(Arrays.asList(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY)), + new HashSet<ProgramSelector.Identifier>(), true, false); + + // Start updates on the clients in order. The HAL filter should get updated after each + // client except [2]. + mTunerSessions[0].startProgramListUpdates(idFilter); + ProgramFilter halFilter = Convert.programFilterToHal(idFilter); + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); + + mTunerSessions[1].startProgramListUpdates(categoryFilter); + halFilter.identifiers.clear(); + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); + + mTunerSessions[2].startProgramListUpdates(typeFilterWithoutModifications); + verify(mHalTunerSessionMock, times(2)).startProgramListUpdates(any()); + + mTunerSessions[3].startProgramListUpdates(typeFilterWithModifications); + halFilter.excludeModifications = false; + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); + + // Adding mRdsInfo should update clients [0] and [1]. + updateHalProgramInfo(false, Arrays.asList(mRdsInfo), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], false, Arrays.asList(mRdsInfo), + null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], false, Arrays.asList(mRdsInfo), + null); + + // Adding mAmFmInfo should update clients [1], [2], and [3]. + updateHalProgramInfo(false, Arrays.asList(mAmFmInfo), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], false, Arrays.asList(mAmFmInfo), + null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[2], false, Arrays.asList(mAmFmInfo), + null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[3], false, Arrays.asList(mAmFmInfo), + null); + + // Modifying mAmFmInfo to mModifiedAmFmInfo should update only [3]. + updateHalProgramInfo(false, Arrays.asList(mModifiedAmFmInfo), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[3], false, + Arrays.asList(mModifiedAmFmInfo), null); + + // Adding mDabEnsembleInfo should not update any client. + updateHalProgramInfo(false, Arrays.asList(mDabEnsembleInfo), null); + verify(mAidlTunerCallbackMocks[0], times(1)).onProgramListUpdated(any()); + verify(mAidlTunerCallbackMocks[1], times(2)).onProgramListUpdated(any()); + verify(mAidlTunerCallbackMocks[2], times(1)).onProgramListUpdated(any()); + verify(mAidlTunerCallbackMocks[3], times(2)).onProgramListUpdated(any()); + } + + @Test + public void testClientClosing() throws RemoteException { + // Open 2 clients that use different filters that are both sensitive to mAmFmIdentifier. + openAidlClients(2); + ProgramList.Filter idFilter = new ProgramList.Filter(new HashSet<Integer>(), + new HashSet<ProgramSelector.Identifier>(Arrays.asList(mAmFmIdentifier)), true, + false); + ProgramList.Filter typeFilter = new ProgramList.Filter( + new HashSet<Integer>(Arrays.asList(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY)), + new HashSet<ProgramSelector.Identifier>(), true, false); + + // Start updates on the clients, and verify the HAL filter is updated after each one. + mTunerSessions[0].startProgramListUpdates(idFilter); + ProgramFilter halFilter = Convert.programFilterToHal(idFilter); + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); + + mTunerSessions[1].startProgramListUpdates(typeFilter); + halFilter.identifiers.clear(); + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); + + // Update the HAL with mAmFmInfo, and verify both clients are updated. + updateHalProgramInfo(true, Arrays.asList(mAmFmInfo), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], true, Arrays.asList(mAmFmInfo), + null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], true, Arrays.asList(mAmFmInfo), + null); + + // Stop updates on the first client and verify the HAL filter is updated. + mTunerSessions[0].stopProgramListUpdates(); + verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(Convert.programFilterToHal( + typeFilter)); + + // Update the HAL with mModifiedAmFmInfo, and verify only the remaining client is updated. + updateHalProgramInfo(true, Arrays.asList(mModifiedAmFmInfo), null); + verify(mAidlTunerCallbackMocks[0], times(1)).onProgramListUpdated(any()); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], true, + Arrays.asList(mModifiedAmFmInfo), null); + + // Close the other client without explicitly stopping updates, and verify HAL updates are + // stopped as well. + mTunerSessions[1].close(); + verify(mHalTunerSessionMock).stopProgramListUpdates(); + } + + private void openAidlClients(int numClients) throws RemoteException { + mAidlTunerCallbackMocks = new android.hardware.radio.ITunerCallback[numClients]; + mTunerSessions = new TunerSession[numClients]; + for (int i = 0; i < numClients; i++) { + mAidlTunerCallbackMocks[i] = mock(android.hardware.radio.ITunerCallback.class); + mTunerSessions[i] = mRadioModule.openSession(mAidlTunerCallbackMocks[i]); + } + } + + private void updateHalProgramInfo(boolean purge, List<RadioManager.ProgramInfo> modified, + List<ProgramSelector.Identifier> removed) throws RemoteException { + ProgramListChunk programListChunk = new ProgramListChunk(); + programListChunk.purge = purge; + programListChunk.complete = true; + if (modified != null) { + for (RadioManager.ProgramInfo mod : modified) { + programListChunk.modified.add(TestUtils.programInfoToHal(mod)); + } + } + if (removed != null) { + for (ProgramSelector.Identifier id : removed) { + programListChunk.removed.add(Convert.programIdentifierToHal(id)); + } + } + mHalTunerCallback.onProgramListUpdated(programListChunk); + } + + private void verifyAidlClientReceivedChunk(android.hardware.radio.ITunerCallback clientMock, + boolean purge, List<RadioManager.ProgramInfo> modified, + List<ProgramSelector.Identifier> removed) throws RemoteException { + HashSet<RadioManager.ProgramInfo> modifiedSet = new HashSet<>(); + if (modified != null) { + modifiedSet.addAll(modified); + } + HashSet<ProgramSelector.Identifier> removedSet = new HashSet<>(); + if (removed != null) { + removedSet.addAll(removed); + } + ProgramList.Chunk expectedChunk = new ProgramList.Chunk(purge, true, modifiedSet, + removedSet); + verify(clientMock).onProgramListUpdated(argThat(new ChunkMatcher(expectedChunk))); + } + + // TODO(b/130750904): Remove this class and replace "argThat(new ChunkMatcher(chunk))" with + // "eq(chunk)". + // + // Ideally, this class wouldn't exist, but currently RadioManager.ProgramInfo#hashCode() can + // return different values for objects that satisfy ProgramInfo#equals(). As a short term + // workaround, this class performs the O(N^2) comparison between the Chunks' mModified sets. + // + // To test if ProgramInfo#hashCode() has been fixed, remove commenting from + // testProgramInfoHashCode() below. + private class ChunkMatcher implements ArgumentMatcher<ProgramList.Chunk> { + private final ProgramList.Chunk mExpected; + + ChunkMatcher(ProgramList.Chunk expected) { + mExpected = expected; + } + + @Override + public boolean matches(ProgramList.Chunk actual) { + if ((mExpected.isPurge() != actual.isPurge()) + || (mExpected.isComplete() != actual.isComplete()) + || (!mExpected.getRemoved().equals(actual.getRemoved()))) { + return false; + } + Set<RadioManager.ProgramInfo> expectedModified = mExpected.getModified(); + Set<RadioManager.ProgramInfo> actualModified = new HashSet<>(actual.getModified()); + if (expectedModified.size() != actualModified.size()) { + return false; + } + for (RadioManager.ProgramInfo expectedInfo : expectedModified) { + boolean found = false; + for (RadioManager.ProgramInfo actualInfo : actualModified) { + if (expectedInfo.equals(actualInfo)) { + found = true; + actualModified.remove(actualInfo); + break; + } + } + if (!found) { + return false; + } + } + return true; + } + } + + // @Test + // public void testProgramInfoHashCode() { + // RadioManager.ProgramInfo info1 = TestUtils.makeProgramInfo( + // ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 0); + // RadioManager.ProgramInfo info2 = TestUtils.makeProgramInfo( + // ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 0); + // assertEquals(info1, info2); + // assertEquals(info1.hashCode(), info2.hashCode()); + // } +} diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TestUtils.java new file mode 100644 index 000000000000..4944803eaafe --- /dev/null +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TestUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.broadcastradio.hal2; + +import android.hardware.broadcastradio.V2_0.ProgramInfo; +import android.hardware.radio.ProgramSelector; +import android.hardware.radio.RadioManager; +import android.hardware.radio.RadioMetadata; + +import java.util.HashMap; + +final class TestUtils { + static RadioManager.ProgramInfo makeProgramInfo(int programType, + ProgramSelector.Identifier identifier, int signalQuality) { + // Note: If you set new fields, check if programInfoToHal() needs to be updated as well. + return new RadioManager.ProgramInfo(new ProgramSelector(programType, identifier, null, + null), null, null, null, 0, signalQuality, new RadioMetadata.Builder().build(), + new HashMap<String, String>()); + } + + static ProgramInfo programInfoToHal(RadioManager.ProgramInfo info) { + // Note that because Convert does not by design provide functions for all conversions, this + // function only copies fields that are set by makeProgramInfo(). + ProgramInfo hwInfo = new ProgramInfo(); + hwInfo.selector = Convert.programSelectorToHal(info.getSelector()); + hwInfo.signalQuality = info.getSignalStrength(); + return hwInfo; + } +} diff --git a/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java new file mode 100644 index 000000000000..b605520c659d --- /dev/null +++ b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.text.format; + +import static org.junit.Assert.assertEquals; + +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Locale; +import java.util.TimeZone; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public class TimeMigrationUtilsTest { + + private static final int ONE_DAY_IN_SECONDS = 24 * 60 * 60; + + private Locale mDefaultLocale; + private TimeZone mDefaultTimeZone; + + @Before + public void setUp() { + mDefaultLocale = Locale.getDefault(); + mDefaultTimeZone = TimeZone.getDefault(); + } + + @After + public void tearDown() { + Locale.setDefault(mDefaultLocale); + TimeZone.setDefault(mDefaultTimeZone); + } + + @Test + public void formatMillisWithFixedFormat_fixes2038Issue() { + Locale.setDefault(Locale.UK); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + + // The following cannot be represented properly using Time because they are outside of the + // supported range. + long y2038Issue1 = (((long) Integer.MIN_VALUE) - ONE_DAY_IN_SECONDS) * 1000L; + assertEquals( + "1901-12-12 20:45:52", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue1)); + long y2038Issue2 = (((long) Integer.MAX_VALUE) + ONE_DAY_IN_SECONDS) * 1000L; + assertEquals( + "2038-01-20 03:14:07", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue2)); + } + + /** + * Compares TimeMigrationUtils.formatSimpleDateTime() with the code it is replacing. + */ + @Test + public void formatMillisAsDateTime_matchesOldBehavior() { + // A selection of interesting locales. + Locale[] locales = new Locale[] { + Locale.US, + Locale.UK, + Locale.FRANCE, + Locale.JAPAN, + Locale.CHINA, + // Android supports RTL locales like arabic and arabic with latin numbers. + Locale.forLanguageTag("ar-AE"), + Locale.forLanguageTag("ar-AE-u-nu-latn"), + }; + // A selection of interesting time zones. + String[] timeZoneIds = new String[] { + "UTC", "Europe/London", "America/New_York", "America/Los_Angeles", "Asia/Shanghai", + }; + // Some arbitrary times when the two formatters should agree. + long[] timesMillis = new long[] { + System.currentTimeMillis(), + 0, + // The Time class only works in 32-bit range, the replacement works beyond that. To + // avoid messing around with offsets and complicating the test, below there are a + // day after / before the known limits. + (Integer.MIN_VALUE + ONE_DAY_IN_SECONDS) * 1000L, + (Integer.MAX_VALUE - ONE_DAY_IN_SECONDS) * 1000L, + }; + + for (Locale locale : locales) { + Locale.setDefault(locale); + for (String timeZoneId : timeZoneIds) { + TimeZone timeZone = TimeZone.getTimeZone(timeZoneId); + TimeZone.setDefault(timeZone); + for (long timeMillis : timesMillis) { + Time time = new Time(); + time.set(timeMillis); + String oldResult = time.format("%Y-%m-%d %H:%M:%S"); + String newResult = TimeMigrationUtils.formatMillisWithFixedFormat(timeMillis); + assertEquals( + "locale=" + locale + ", timeZoneId=" + timeZoneId + + ", timeMillis=" + timeMillis, + oldResult, newResult); + } + } + } + } +} diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java index adaae5cdba8d..682416c58c72 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java @@ -132,6 +132,8 @@ public class AccessibilityServiceConnectionImpl extends IAccessibilityServiceCon public void sendGesture(int sequence, ParceledListSlice gestureSteps) {} + public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) {} + public boolean isFingerprintGestureDetectionAvailable() { return false; } diff --git a/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java index 008085e38dbf..a93573724ba1 100644 --- a/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java +++ b/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java @@ -68,12 +68,7 @@ public class KernelWakelockReaderTest extends TestCase { private WakeLockInfo createWakeLockInfo(String name, int activeCount, long totalTime) { WakeLockInfo info = new WakeLockInfo(); info.name = name; - info.pid = 1; info.activeCount = activeCount; - info.isActive = true; - info.activeSince = 0; - info.lastChange = 0; - info.maxTime = 0; info.totalTime = totalTime; return info; } @@ -89,7 +84,7 @@ public class KernelWakelockReaderTest extends TestCase { byte[] buffer, WakeLockInfo[] wlStats) { mReader.updateVersion(staleStats); mReader.parseProcWakelocks(buffer, buffer.length, true, staleStats); - mReader.getNativeWakelockStats(wlStats, staleStats); + mReader.updateWakelockStats(wlStats, staleStats); return mReader.removeOldStats(staleStats); } @@ -101,7 +96,7 @@ public class KernelWakelockReaderTest extends TestCase { mReader = new KernelWakelockReader(); } -// ------------------------- Kernel Wakelock Stats Test ------------------------ +// ------------------------- Legacy Wakelock Stats Test ------------------------ @SmallTest public void testParseEmptyFile() throws Exception { KernelWakelockStats staleStats = mReader.parseProcWakelocks(new byte[0], 0, true, @@ -196,10 +191,10 @@ public class KernelWakelockReaderTest extends TestCase { assertFalse(staleStats.containsKey("Fakelock")); } -// -------------------- Native (SystemSuspend) Wakelock Stats Test ------------------- +// -------------------- SystemSuspend Wakelock Stats Test ------------------- @SmallTest public void testEmptyWakeLockInfoList() { - KernelWakelockStats staleStats = mReader.getNativeWakelockStats(new WakeLockInfo[0], + KernelWakelockStats staleStats = mReader.updateWakelockStats(new WakeLockInfo[0], new KernelWakelockStats()); assertTrue(staleStats.isEmpty()); @@ -208,9 +203,9 @@ public class KernelWakelockReaderTest extends TestCase { @SmallTest public void testOneWakeLockInfo() { WakeLockInfo[] wlStats = new WakeLockInfo[1]; - wlStats[0] = createWakeLockInfo("WakeLock", 20, 10000); + wlStats[0] = createWakeLockInfo("WakeLock", 20, 1000); // Milliseconds - KernelWakelockStats staleStats = mReader.getNativeWakelockStats(wlStats, + KernelWakelockStats staleStats = mReader.updateWakelockStats(wlStats, new KernelWakelockStats()); assertEquals(1, staleStats.size()); @@ -219,16 +214,16 @@ public class KernelWakelockReaderTest extends TestCase { KernelWakelockStats.Entry entry = staleStats.get("WakeLock"); assertEquals(20, entry.mCount); - assertEquals(10000, entry.mTotalTime); + assertEquals(1000 * 1000, entry.mTotalTime); // Microseconds } @SmallTest public void testTwoWakeLockInfos() { WakeLockInfo[] wlStats = new WakeLockInfo[2]; - wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); - wlStats[1] = createWakeLockInfo("WakeLock2", 20, 2000); + wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); // Milliseconds + wlStats[1] = createWakeLockInfo("WakeLock2", 20, 2000); // Milliseconds - KernelWakelockStats staleStats = mReader.getNativeWakelockStats(wlStats, + KernelWakelockStats staleStats = mReader.updateWakelockStats(wlStats, new KernelWakelockStats()); assertEquals(2, staleStats.size()); @@ -238,17 +233,17 @@ public class KernelWakelockReaderTest extends TestCase { KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1"); assertEquals(10, entry1.mCount); - assertEquals(1000, entry1.mTotalTime); + assertEquals(1000 * 1000, entry1.mTotalTime); // Microseconds KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2"); assertEquals(20, entry2.mCount); - assertEquals(2000, entry2.mTotalTime); + assertEquals(2000 * 1000, entry2.mTotalTime); // Microseconds } @SmallTest public void testWakeLockInfosBecomeStale() { WakeLockInfo[] wlStats = new WakeLockInfo[1]; - wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); + wlStats[0] = createWakeLockInfo("WakeLock1", 10, 1000); // Milliseconds KernelWakelockStats staleStats = new KernelWakelockStats(); @@ -259,9 +254,9 @@ public class KernelWakelockReaderTest extends TestCase { assertTrue(staleStats.containsKey("WakeLock1")); KernelWakelockStats.Entry entry = staleStats.get("WakeLock1"); assertEquals(10, entry.mCount); - assertEquals(1000, entry.mTotalTime); + assertEquals(1000 * 1000, entry.mTotalTime); // Microseconds - wlStats[0] = createWakeLockInfo("WakeLock2", 20, 2000); + wlStats[0] = createWakeLockInfo("WakeLock2", 20, 2000); // Milliseconds readKernelWakelockStats(staleStats, new byte[0], wlStats); @@ -271,146 +266,6 @@ public class KernelWakelockReaderTest extends TestCase { assertTrue(staleStats.containsKey("WakeLock2")); entry = staleStats.get("WakeLock2"); assertEquals(20, entry.mCount); - assertEquals(2000, entry.mTotalTime); - } - -// -------------------- Aggregate Wakelock Stats Tests -------------------- - @SmallTest - public void testAggregateStatsEmpty() throws Exception { - KernelWakelockStats staleStats = new KernelWakelockStats(); - - byte[] buffer = new byte[0]; - WakeLockInfo[] wlStats = new WakeLockInfo[0]; - - readKernelWakelockStats(staleStats, buffer, wlStats); - - assertTrue(staleStats.isEmpty()); - } - - @SmallTest - public void testAggregateStatsNoNativeWakelocks() throws Exception { - KernelWakelockStats staleStats = new KernelWakelockStats(); - - byte[] buffer = new ProcFileBuilder() - .addLine("Wakelock", 34, 123) // Milliseconds - .getBytes(); - WakeLockInfo[] wlStats = new WakeLockInfo[0]; - - readKernelWakelockStats(staleStats, buffer, wlStats); - - assertEquals(1, staleStats.size()); - - assertTrue(staleStats.containsKey("Wakelock")); - - KernelWakelockStats.Entry entry = staleStats.get("Wakelock"); - assertEquals(34, entry.mCount); - assertEquals(1000 * 123, entry.mTotalTime); // Microseconds - } - - @SmallTest - public void testAggregateStatsNoKernelWakelocks() throws Exception { - KernelWakelockStats staleStats = new KernelWakelockStats(); - - byte[] buffer = new byte[0]; - WakeLockInfo[] wlStats = new WakeLockInfo[1]; - wlStats[0] = createWakeLockInfo("WakeLock", 10, 1000); - - readKernelWakelockStats(staleStats, buffer, wlStats); - - assertEquals(1, staleStats.size()); - - assertTrue(staleStats.containsKey("WakeLock")); - - KernelWakelockStats.Entry entry = staleStats.get("WakeLock"); - assertEquals(10, entry.mCount); - assertEquals(1000, entry.mTotalTime); - } - - @SmallTest - public void testAggregateStatsBothKernelAndNativeWakelocks() throws Exception { - KernelWakelockStats staleStats = new KernelWakelockStats(); - - byte[] buffer = new ProcFileBuilder() - .addLine("WakeLock1", 34, 123) // Milliseconds - .getBytes(); - WakeLockInfo[] wlStats = new WakeLockInfo[1]; - wlStats[0] = createWakeLockInfo("WakeLock2", 10, 1000); - - readKernelWakelockStats(staleStats, buffer, wlStats); - - assertEquals(2, staleStats.size()); - - assertTrue(staleStats.containsKey("WakeLock1")); - KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1"); - assertEquals(34, entry1.mCount); - assertEquals(123 * 1000, entry1.mTotalTime); // Microseconds - - assertTrue(staleStats.containsKey("WakeLock2")); - KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2"); - assertEquals(10, entry2.mCount); - assertEquals(1000, entry2.mTotalTime); - } - - @SmallTest - public void testAggregateStatsUpdate() throws Exception { - KernelWakelockStats staleStats = new KernelWakelockStats(); - - byte[] buffer = new ProcFileBuilder() - .addLine("WakeLock1", 34, 123) // Milliseconds - .addLine("WakeLock2", 46, 345) // Milliseconds - .getBytes(); - WakeLockInfo[] wlStats = new WakeLockInfo[2]; - wlStats[0] = createWakeLockInfo("WakeLock3", 10, 1000); - wlStats[1] = createWakeLockInfo("WakeLock4", 20, 2000); - - readKernelWakelockStats(staleStats, buffer, wlStats); - - assertEquals(4, staleStats.size()); - - assertTrue(staleStats.containsKey("WakeLock1")); - assertTrue(staleStats.containsKey("WakeLock2")); - assertTrue(staleStats.containsKey("WakeLock3")); - assertTrue(staleStats.containsKey("WakeLock4")); - - KernelWakelockStats.Entry entry1 = staleStats.get("WakeLock1"); - assertEquals(34, entry1.mCount); - assertEquals(123 * 1000, entry1.mTotalTime); // Microseconds - - KernelWakelockStats.Entry entry2 = staleStats.get("WakeLock2"); - assertEquals(46, entry2.mCount); - assertEquals(345 * 1000, entry2.mTotalTime); // Microseconds - - KernelWakelockStats.Entry entry3 = staleStats.get("WakeLock3"); - assertEquals(10, entry3.mCount); - assertEquals(1000, entry3.mTotalTime); - - KernelWakelockStats.Entry entry4 = staleStats.get("WakeLock4"); - assertEquals(20, entry4.mCount); - assertEquals(2000, entry4.mTotalTime); - - buffer = new ProcFileBuilder() - .addLine("WakeLock1", 45, 789) // Milliseconds - .addLine("WakeLock1", 56, 123) // Milliseconds - .getBytes(); - wlStats = new WakeLockInfo[1]; - wlStats[0] = createWakeLockInfo("WakeLock4", 40, 4000); - - readKernelWakelockStats(staleStats, buffer, wlStats); - - assertEquals(2, staleStats.size()); - - assertTrue(staleStats.containsKey("WakeLock1")); - assertTrue(staleStats.containsKey("WakeLock4")); - - assertFalse(staleStats.containsKey("WakeLock2")); - assertFalse(staleStats.containsKey("WakeLock3")); - - entry1 = staleStats.get("WakeLock1"); - assertEquals(45 + 56, entry1.mCount); - assertEquals((789 + 123) * 1000, entry1.mTotalTime); // Microseconds - - entry2 = staleStats.get("WakeLock4"); - assertEquals(40, entry2.mCount); - assertEquals(4000, entry4.mTotalTime); + assertEquals(2000 * 1000, entry.mTotalTime); // Micro seconds } } diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index ae7fe6c46f2f..0e635c774c84 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -63,7 +63,7 @@ import java.lang.annotation.RetentionPolicy; * <h3>Creating a RenderNode</h3> * <pre class="prettyprint"> * RenderNode renderNode = new RenderNode("myRenderNode"); - * renderNode.setLeftTopRightBottom(0, 0, 50, 50); // Set the size to 50x50 + * renderNode.setPosition(0, 0, 50, 50); // Set the size to 50x50 * RecordingCanvas canvas = renderNode.beginRecording(); * try { * // Draw with the canvas @@ -104,7 +104,7 @@ import java.lang.annotation.RetentionPolicy; * <pre class="prettyprint"> * private void createDisplayList() { * mRenderNode = new RenderNode("MyRenderNode"); - * mRenderNode.setLeftTopRightBottom(0, 0, width, height); + * mRenderNode.setPosition(0, 0, width, height); * RecordingCanvas canvas = mRenderNode.beginRecording(); * try { * for (Bitmap b : mBitmaps) { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 6ea6af8f2935..f01b1bfa780d 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -778,6 +778,13 @@ void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, mCanvas->drawDrawable(drawable.get()); } +void SkiaCanvas::drawPicture(const SkPicture& picture) { + // TODO: Change to mCanvas->drawPicture()? SkCanvas::drawPicture seems to be + // where the logic is for playback vs. ref picture. Using picture.playback here + // to stay behavior-identical for now, but should revisit this at some point. + picture.playback(mCanvas); +} + // ---------------------------------------------------------------------------- // Canvas draw operations: View System // ---------------------------------------------------------------------------- diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 05a6d0dda42d..799a89158298 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -46,8 +46,6 @@ public: virtual ~SkiaCanvas(); - virtual SkCanvas* asSkCanvas() override { return mCanvas; } - virtual void resetRecording(int width, int height, uirenderer::RenderNode* renderNode) override { LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas"); @@ -155,9 +153,11 @@ public: virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override; virtual void callDrawGLFunction(Functor* functor, uirenderer::GlFunctorLifecycleListener* listener) override; + virtual void drawPicture(const SkPicture& picture) override; protected: SkiaCanvas(); + SkCanvas* asSkCanvas() { return mCanvas; } void reset(SkCanvas* skiaCanvas); void drawDrawable(SkDrawable* drawable) { mCanvas->drawDrawable(drawable); } diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index ac8db216b059..ee4fa1d689ef 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -131,20 +131,6 @@ public: */ static void setCompatibilityVersion(int apiLevel); - /** - * Provides a Skia SkCanvas interface that acts as a proxy to this Canvas. - * It is useful for testing and clients (e.g. Picture/Movie) that expect to - * draw their contents into an SkCanvas. - * - * The SkCanvas returned is *only* valid until another Canvas call is made - * that would change state (e.g. matrix or clip). Clients of asSkCanvas() - * are responsible for *not* persisting this pointer. - * - * Further, the returned SkCanvas should NOT be unref'd and is valid until - * this canvas is destroyed or a new bitmap is set. - */ - virtual SkCanvas* asSkCanvas() = 0; - virtual void setBitmap(const SkBitmap& bitmap) = 0; virtual bool isOpaque() = 0; @@ -264,6 +250,7 @@ public: const SkPaint* paint) = 0; virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) = 0; + virtual void drawPicture(const SkPicture& picture) = 0; /** * Specifies if the positions passed to ::drawText are absolute or relative diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 550c27d7a051..d97c5ed4c7f5 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -145,7 +145,8 @@ void CanvasContext::setSurface(sp<Surface>&& surface) { if (surface) { mNativeSurface = new ReliableSurface{std::move(surface)}; - mNativeSurface->setDequeueTimeout(500_ms); + // TODO: Fix error handling & re-shorten timeout + mNativeSurface->setDequeueTimeout(4000_ms); } else { mNativeSurface = nullptr; } diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp index f6178aff0c2e..2ed1b25efc71 100644 --- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp +++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp @@ -78,7 +78,7 @@ TEST(SkiaCanvas, colorSpaceXform) { sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); // Playback to a software sRGB canvas. The result should be fully red. - canvas.asSkCanvas()->drawPicture(picture); + canvas.drawPicture(*picture); ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0)); } diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 353e58e98efa..7906fa34d844 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -246,7 +246,7 @@ import java.util.Vector; * via {@link #setOnBufferingUpdateListener(OnBufferingUpdateListener)}. * This callback allows applications to keep track of the buffering status * while streaming audio/video.</li> - * <li>Calling {@link #start()} has not effect + * <li>Calling {@link #start()} has no effect * on a MediaPlayer object that is already in the <em>Started</em> state.</li> * </ul> * </li> diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp index 1e9a194d76c8..357bb5e50eee 100644 --- a/media/native/midi/amidi.cpp +++ b/media/native/midi/amidi.cpp @@ -122,7 +122,7 @@ static std::mutex openMutex; // Ensure that the device can be connected just onc * - AMEDIA_ERROR_INVALID_PARAMETER * AMEDIA_ERROR_UNKNOWN */ -static media_status_t AMIDI_API AMIDI_getDeviceInfo(const AMidiDevice *device, +static media_status_t AMIDI_getDeviceInfo(const AMidiDevice *device, AMidiDeviceInfo *outDeviceInfoPtr) { if (device == nullptr) { return AMEDIA_ERROR_INVALID_PARAMETER; @@ -142,7 +142,7 @@ static media_status_t AMIDI_API AMIDI_getDeviceInfo(const AMidiDevice *device, return AMEDIA_OK; } -media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj, +media_status_t AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj, AMidiDevice** devicePtrPtr) { if (j_midiDeviceObj == nullptr) { @@ -188,7 +188,7 @@ media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceO return AMEDIA_OK; } -media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *device) +media_status_t AMidiDevice_release(const AMidiDevice *device) { if (device == nullptr || device->midiDeviceObj == nullptr) { return AMEDIA_ERROR_INVALID_PARAMETER; @@ -217,21 +217,21 @@ media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *device) return AMEDIA_OK; } -int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) { +int32_t AMidiDevice_getType(const AMidiDevice *device) { if (device == nullptr) { return AMEDIA_ERROR_INVALID_PARAMETER; } return device->deviceInfo.type; } -ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) { +ssize_t AMidiDevice_getNumInputPorts(const AMidiDevice *device) { if (device == nullptr) { return AMEDIA_ERROR_INVALID_PARAMETER; } return device->deviceInfo.inputPortCount; } -ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) { +ssize_t AMidiDevice_getNumOutputPorts(const AMidiDevice *device) { if (device == nullptr) { return AMEDIA_ERROR_INVALID_PARAMETER; } @@ -291,7 +291,7 @@ static void AMIDI_closePort(AMIDI_Port *port) { /* * Output (receiving) API */ -media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber, +media_status_t AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber, AMidiOutputPort **outOutputPortPtr) { return AMIDI_openPort(device, portNumber, PORTTYPE_OUTPUT, (AMIDI_Port**)outOutputPortPtr); } @@ -350,7 +350,7 @@ private: AMIDI_Port *mPort; }; -ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr, +ssize_t AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr, uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *timestampPtr) { if (outputPort == nullptr || buffer == nullptr) { @@ -361,19 +361,19 @@ ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int numBytesReceivedPtr, timestampPtr); } -void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) { +void AMidiOutputPort_close(const AMidiOutputPort *outputPort) { AMIDI_closePort((AMIDI_Port*)outputPort); } /* * Input (sending) API */ -media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber, +media_status_t AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber, AMidiInputPort **outInputPortPtr) { return AMIDI_openPort(device, portNumber, PORTTYPE_INPUT, (AMIDI_Port**)outInputPortPtr); } -void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) { +void AMidiInputPort_close(const AMidiInputPort *inputPort) { AMIDI_closePort((AMIDI_Port*)inputPort); } @@ -386,12 +386,12 @@ static ssize_t AMIDI_makeSendBuffer( return numBytes + AMIDI_PACKET_OVERHEAD; } -ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer, +ssize_t AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer, size_t numBytes) { return AMidiInputPort_sendWithTimestamp(inputPort, buffer, numBytes, 0); } -ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort, +ssize_t AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort, const uint8_t *data, size_t numBytes, int64_t timestamp) { if (inputPort == nullptr || data == nullptr) { return AMEDIA_ERROR_INVALID_PARAMETER; @@ -423,7 +423,7 @@ ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPo return numSent; } -media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) { +media_status_t AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) { if (inputPort == nullptr) { return AMEDIA_ERROR_INVALID_PARAMETER; } diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h index cbe410f46af9..76dec0f7e723 100644 --- a/media/native/midi/include/amidi/AMidi.h +++ b/media/native/midi/include/amidi/AMidi.h @@ -41,8 +41,6 @@ typedef struct AMidiDevice AMidiDevice; typedef struct AMidiInputPort AMidiInputPort; typedef struct AMidiOutputPort AMidiOutputPort; -#define AMIDI_API __attribute__((visibility("default"))) - /* * Message Op Codes. Used to parse MIDI data packets */ @@ -61,6 +59,8 @@ enum { AMIDI_DEVICE_TYPE_BLUETOOTH = 3 /* A MIDI device connected via BlueTooth */ }; +#if __ANDROID_API__ >= 29 + /* * Device API */ @@ -78,7 +78,7 @@ enum { * is null or already connected to a native AMidiDevice * @see AMEDIA_ERROR_UNKNOWN - an unknown error occurred. */ -media_status_t AMIDI_API AMidiDevice_fromJava( +media_status_t AMidiDevice_fromJava( JNIEnv *env, jobject midiDeviceObj, AMidiDevice **outDevicePtrPtr) __INTRODUCED_IN(29); /** @@ -93,7 +93,7 @@ media_status_t AMIDI_API AMidiDevice_fromJava( * @see AMEDIA_ERROR_INVALID_OBJECT - the JNI interface initialization to the associated java MidiDevice failed. * @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info. */ -media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29); +media_status_t AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29); /** * Gets the MIDI device type. @@ -108,7 +108,7 @@ media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *midiDevice) __IN * @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL. * @see AMEDIA_ERROR_UNKNOWN - Unknown error. */ -int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29); +int32_t AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29); /** * Gets the number of input (sending) ports available on the specified MIDI device. @@ -120,7 +120,7 @@ int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN * @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL. * @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info. */ -ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29); +ssize_t AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29); /** * Gets the number of output (receiving) ports available on the specified MIDI device. @@ -132,7 +132,7 @@ ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTR * @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL. * @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info. */ -ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29); +ssize_t AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29); /* * API for receiving data from the Output port of a device. @@ -150,7 +150,7 @@ ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INT * @return AMEDIA_OK, or a negative error code: * @see AMEDIA_ERROR_UNKNOWN - Unknown Error. */ -media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber, +media_status_t AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber, AMidiOutputPort **outOutputPortPtr) __INTRODUCED_IN(29); /** @@ -158,7 +158,7 @@ media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t * * @param outputPort The native API port identifier of the port. */ -void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29); +void AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29); /** * Receives the next pending MIDI message. To retrieve all pending messages, the client should @@ -178,7 +178,7 @@ void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTROD * @return the number of messages received (either 0 or 1), or a negative error code: * @see AMEDIA_ERROR_UNKNOWN - Unknown Error. */ -ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr, +ssize_t AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr, uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *outTimestampPtr) __INTRODUCED_IN(29); /* @@ -197,7 +197,7 @@ ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int * @return AMEDIA_OK, or a negative error code: * @see AMEDIA_ERROR_UNKNOWN - Unknown Error. */ -media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber, +media_status_t AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber, AMidiInputPort **outInputPortPtr) __INTRODUCED_IN(29); /** @@ -210,7 +210,7 @@ media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t * @return The number of bytes sent, which could be less than specified or a negative error code: * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL. */ -ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer, +ssize_t AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer, size_t numBytes) __INTRODUCED_IN(29); /** @@ -224,7 +224,7 @@ ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uin * @return The number of bytes sent, which could be less than specified or a negative error code: * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL. */ -ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort, +ssize_t AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort, const uint8_t *buffer, size_t numBytes, int64_t timestamp) __INTRODUCED_IN(29); /** @@ -238,14 +238,16 @@ ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPo * @see AMEDIA_ERROR_UNSUPPORTED - The FLUSH command couldn't * be sent. */ -media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29); +media_status_t AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29); /** * Closes the input port. * * @param inputPort Identifies the input (sending) port to close. */ -void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29); +void AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ #ifdef __cplusplus } diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml index 7592bd227a94..fb422aff51ef 100644 --- a/packages/CarSystemUI/res/values/dimens.xml +++ b/packages/CarSystemUI/res/values/dimens.xml @@ -114,10 +114,10 @@ <!-- Car notification shade--> <dimen name="notification_shade_handle_bar_height">10dp</dimen> <dimen name="notification_shade_handle_bar_radius">20dp</dimen> - <dimen name="notification_shade_handle_bar_margin_start">500dp</dimen> - <dimen name="notification_shade_handle_bar_margin_end">500dp</dimen> + <dimen name="notification_shade_handle_bar_margin_start">200dp</dimen> + <dimen name="notification_shade_handle_bar_margin_end">200dp</dimen> <dimen name="notification_shade_handle_bar_margin_top">20dp</dimen> <dimen name="notification_shade_handle_bar_margin_bottom">10dp</dimen> - <dimen name="notification_shade_list_padding_bottom">0dp</dimen> + <dimen name="notification_shade_list_padding_bottom">50dp</dimen> </resources> diff --git a/packages/CtsShim/build/Android.mk b/packages/CtsShim/build/Android.mk index 03eb0d9aad5a..0ef4654d72e7 100644 --- a/packages/CtsShim/build/Android.mk +++ b/packages/CtsShim/build/Android.mk @@ -65,6 +65,9 @@ LOCAL_FULL_MANIFEST_FILE := $(gen) LOCAL_MULTILIB := both LOCAL_JNI_SHARED_LIBRARIES := libshim_jni +# Explicitly uncompress native libs rather than letting the build system doing it and destroy the +# v2/v3 signature. +LOCAL_USE_EMBEDDED_NATIVE_LIBS := true LOCAL_USE_AAPT2 := true diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index b11df4890e98..7d56868d0ce8 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -56,6 +56,7 @@ import java.time.DateTimeException; import java.util.Arrays; import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.zip.CRC32; /** @@ -241,6 +242,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { HashSet<String> movedToGlobal = new HashSet<String>(); Settings.System.getMovedToGlobalSettings(movedToGlobal); Settings.Secure.getMovedToGlobalSettings(movedToGlobal); + Set<String> movedToSecure = getMovedToSecureSettings(); + byte[] restoredWifiSupplicantData = null; byte[] restoredWifiIpConfigData = null; @@ -259,16 +262,17 @@ public class SettingsBackupAgent extends BackupAgentHelper { switch (key) { case KEY_SYSTEM : - restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal); + restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal, + movedToSecure); mSettingsHelper.applyAudioSettings(); break; case KEY_SECURE : - restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal); + restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal, null); break; case KEY_GLOBAL : - restoreSettings(data, Settings.Global.CONTENT_URI, null); + restoreSettings(data, Settings.Global.CONTENT_URI, null, movedToSecure); break; case KEY_WIFI_SUPPLICANT : @@ -347,20 +351,22 @@ public class SettingsBackupAgent extends BackupAgentHelper { HashSet<String> movedToGlobal = new HashSet<String>(); Settings.System.getMovedToGlobalSettings(movedToGlobal); Settings.Secure.getMovedToGlobalSettings(movedToGlobal); + Set<String> movedToSecure = getMovedToSecureSettings(); // system settings data first int nBytes = in.readInt(); if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of settings data"); byte[] buffer = new byte[nBytes]; in.readFully(buffer, 0, nBytes); - restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal); + restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal, + movedToSecure); // secure settings nBytes = in.readInt(); if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data"); if (nBytes > buffer.length) buffer = new byte[nBytes]; in.readFully(buffer, 0, nBytes); - restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal); + restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, null); // Global only if sufficiently new if (version >= FULL_BACKUP_ADDED_GLOBAL) { @@ -369,7 +375,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { if (nBytes > buffer.length) buffer = new byte[nBytes]; in.readFully(buffer, 0, nBytes); movedToGlobal.clear(); // no redirection; this *is* the global namespace - restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal); + restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal, + movedToSecure); } // locale @@ -440,6 +447,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { } } + private Set<String> getMovedToSecureSettings() { + Set<String> movedToSecureSettings = new HashSet<>(); + Settings.Global.getMovedToSecureSettings(movedToSecureSettings); + Settings.System.getMovedToSecureSettings(movedToSecureSettings); + return movedToSecureSettings; + } + private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException { long[] stateChecksums = new long[STATE_SIZE]; @@ -564,7 +578,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { } private void restoreSettings(BackupDataInput data, Uri contentUri, - HashSet<String> movedToGlobal) { + HashSet<String> movedToGlobal, Set<String> movedToSecure) { byte[] settings = new byte[data.getDataSize()]; try { data.readEntityData(settings, 0, settings.length); @@ -572,11 +586,11 @@ public class SettingsBackupAgent extends BackupAgentHelper { Log.e(TAG, "Couldn't read entity data"); return; } - restoreSettings(settings, settings.length, contentUri, movedToGlobal); + restoreSettings(settings, settings.length, contentUri, movedToGlobal, movedToSecure); } private void restoreSettings(byte[] settings, int bytes, Uri contentUri, - HashSet<String> movedToGlobal) { + HashSet<String> movedToGlobal, Set<String> movedToSecure) { if (DEBUG) { Log.i(TAG, "restoreSettings: " + contentUri); } @@ -651,9 +665,14 @@ public class SettingsBackupAgent extends BackupAgentHelper { continue; } - final Uri destination = (movedToGlobal != null && movedToGlobal.contains(key)) - ? Settings.Global.CONTENT_URI - : contentUri; + final Uri destination; + if (movedToGlobal != null && movedToGlobal.contains(key)) { + destination = Settings.Global.CONTENT_URI; + } else if (movedToSecure != null && movedToSecure.contains(key)) { + destination = Settings.Secure.CONTENT_URI; + } else { + destination = contentUri; + } settingsHelper.restoreValue(this, cr, contentValues, destination, key, value, mRestoredFromSdkInt); diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 39d0a0a83f30..a7b44443fc9c 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -350,18 +350,19 @@ public class BugreportProgressService extends Service { private final class BugreportCallbackImpl extends BugreportCallback { - private final int mId; private final BugreportInfo mInfo; - BugreportCallbackImpl(String name, int id) { - mId = id; + BugreportCallbackImpl(String name) { // pid not used in this workflow, so setting default = 0 - mInfo = new BugreportInfo(mContext, mId, 0 /* pid */, name, + mInfo = new BugreportInfo(mContext, 0 /* pid */, name, 100 /* max progress*/); } @Override public void onProgress(float progress) { + if (progress == 0) { + trackInfoWithId(); + } checkProgressUpdated(mInfo, (int) progress); } @@ -369,17 +370,34 @@ public class BugreportProgressService extends Service { // Logging errors and removing progress notification for now. @Override public void onError(@BugreportErrorCode int errorCode) { - stopProgress(mId); + trackInfoWithId(); + stopProgress(mInfo.id); Log.e(TAG, "Bugreport API callback onError() errorCode = " + errorCode); return; } @Override public void onFinished() { + trackInfoWithId(); // Stop running on foreground, otherwise share notification cannot be dismissed. - onBugreportFinished(mId); + onBugreportFinished(mInfo.id); stopSelfWhenDone(); } + + /** + * Reads bugreport id and links it to the bugreport info to track the bugreport's + * progress/completion/error. id is incremented in dumpstate code. This function is called + * when dumpstate calls one of the callback functions (onProgress, onFinished, onError) + * after the id has been incremented. + */ + private void trackInfoWithId() { + final int id = SystemProperties.getInt(PROPERTY_LAST_ID, 1); + if (mBugreportInfos.get(id) == null) { + mInfo.id = id; + mBugreportInfos.put(mInfo.id, mInfo); + } + return; + } } /** @@ -570,19 +588,15 @@ public class BugreportProgressService extends Service { mBugreportManager = (BugreportManager) mContext.getSystemService( Context.BUGREPORT_SERVICE); final Executor executor = ActivityThread.currentActivityThread().getExecutor(); - // TODO(b/123617758): This id should come from dumpstate. - // Dumpstate increments PROPERTY_LAST_ID, may be racy if multiple calls - // to dumpstate are made simultaneously. - final int id = SystemProperties.getInt(PROPERTY_LAST_ID, 0) + 1; + Log.i(TAG, "bugreport type = " + bugreportType + " bugreport file fd: " + bugreportFd + " screenshot file fd: " + screenshotFd); - BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl(bugreportName, id); + BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl(bugreportName); try { mBugreportManager.startBugreport(bugreportFd, screenshotFd, new BugreportParams(bugreportType), executor, bugreportCallback); - mBugreportInfos.put(bugreportCallback.mInfo.id, bugreportCallback.mInfo); } catch (RuntimeException e) { Log.i(TAG, "error in generating bugreports: ", e); // The binder call didn't go through successfully, so need to close the fds. @@ -1816,7 +1830,7 @@ public class BugreportProgressService extends Service { /** * Sequential, user-friendly id used to identify the bugreport. */ - final int id; + int id; /** * {@code pid} of the {@code dumpstate} process generating the bugreport. @@ -1908,8 +1922,15 @@ public class BugreportProgressService extends Service { * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_STARTED. */ BugreportInfo(Context context, int id, int pid, String name, int max) { - this.context = context; + this(context, pid, name, max); this.id = id; + } + + /** + * Constructor for tracked bugreports - typically called upon receiving BUGREPORT_REQUESTED. + */ + BugreportInfo(Context context, int pid, String name, int max) { + this.context = context; this.pid = pid; this.name = name; this.max = this.realMax = max; diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.bp b/packages/SystemUI/plugin/ExamplePlugin/Android.bp index a0eaf14f4a06..c6c80f3780a3 100644 --- a/packages/SystemUI/plugin/ExamplePlugin/Android.bp +++ b/packages/SystemUI/plugin/ExamplePlugin/Android.bp @@ -11,4 +11,5 @@ android_app { srcs: ["src/**/*.java"], + platform_apis: true, } diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index f124d89070bf..6becd21984b9 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -75,14 +75,15 @@ <attr name="horizontalSpacing" format="dimension" /> </declare-styleable> - <!-- Theme for icons in the status bar (light/dark). background/fillColor is used for dual tone - icons like wifi and signal, and singleToneColor is used for icons with only one tone. + <!-- Theme for icons in the status/nav bar (light/dark). background/fillColor is used for dual + tone icons like wifi and signal, and singleToneColor is used for icons with only one tone. Contract: Pixel with fillColor blended over backgroundColor blended over translucent should equal to singleToneColor blended over translucent. --> <declare-styleable name="TonedIcon"> <attr name="backgroundColor" format="integer" /> <attr name="fillColor" format="integer" /> <attr name="singleToneColor" format="integer" /> + <attr name="homeHandleColor" format="integer" /> </declare-styleable> <declare-styleable name="StatusBarWindowView_Layout"> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index e7a1a660abc2..61816f60d0ba 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -116,6 +116,9 @@ <!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* --> <color name="navigation_bar_icon_color">#E5FFFFFF</color> + <color name="navigation_bar_home_handle_light_color">#EBffffff</color> + <color name="navigation_bar_home_handle_dark_color">#99000000</color> + <!-- The shadow color for light navigation bar icons. --> <color name="nav_key_button_shadow_color">#30000000</color> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 2f1770a39f02..6374191c4d7b 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -366,11 +366,13 @@ <item name="backgroundColor">@color/light_mode_icon_color_dual_tone_background</item> <item name="fillColor">@color/light_mode_icon_color_dual_tone_fill</item> <item name="singleToneColor">@color/light_mode_icon_color_single_tone</item> + <item name="homeHandleColor">@color/navigation_bar_home_handle_light_color</item> </style> <style name="DualToneDarkTheme"> <item name="backgroundColor">@color/dark_mode_icon_color_dual_tone_background</item> <item name="fillColor">@color/dark_mode_icon_color_dual_tone_fill</item> <item name="singleToneColor">@color/dark_mode_icon_color_single_tone</item> + <item name="homeHandleColor">@color/navigation_bar_home_handle_dark_color</item> </style> <style name="QSHeaderDarkTheme"> <item name="backgroundColor">@color/dark_mode_qs_icon_color_dual_tone_background</item> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java index 53403aa4dbf1..a7e3c59ce72e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java @@ -171,15 +171,21 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener, allowMultiple, mLooper, cls, this); p.loadAll(); - mPluginMap.put(listener, p); + synchronized (this) { + mPluginMap.put(listener, p); + } startListening(); } public void removePluginListener(PluginListener<?> listener) { - if (!mPluginMap.containsKey(listener)) return; - mPluginMap.remove(listener).destroy(); - if (mPluginMap.size() == 0) { - stopListening(); + synchronized (this) { + if (!mPluginMap.containsKey(listener)) { + return; + } + mPluginMap.remove(listener).destroy(); + if (mPluginMap.size() == 0) { + stopListening(); + } } } @@ -208,8 +214,10 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) { - for (PluginInstanceManager manager : mPluginMap.values()) { - manager.loadAll(); + synchronized (this) { + for (PluginInstanceManager manager : mPluginMap.values()) { + manager.loadAll(); + } } } else if (DISABLE_PLUGIN.equals(intent.getAction())) { Uri uri = intent.getData(); @@ -274,13 +282,15 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage getPluginEnabler().setEnabled(componentName); } } - if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { - for (PluginInstanceManager manager : mPluginMap.values()) { - manager.onPackageChange(pkg); - } - } else { - for (PluginInstanceManager manager : mPluginMap.values()) { - manager.onPackageRemoved(pkg); + synchronized (this) { + if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { + for (PluginInstanceManager manager : mPluginMap.values()) { + manager.onPackageChange(pkg); + } + } else { + for (PluginInstanceManager manager : mPluginMap.values()) { + manager.onPackageRemoved(pkg); + } } } } @@ -322,9 +332,11 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public <T> boolean dependsOn(Plugin p, Class<T> cls) { - for (int i = 0; i < mPluginMap.size(); i++) { - if (mPluginMap.valueAt(i).dependsOn(p, cls)) { - return true; + synchronized (this) { + for (int i = 0; i < mPluginMap.size(); i++) { + if (mPluginMap.valueAt(i).dependsOn(p, cls)) { + return true; + } } } return false; @@ -335,10 +347,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(String.format(" plugin map (%d):", mPluginMap.size())); - for (PluginListener listener: mPluginMap.keySet()) { - pw.println(String.format(" %s -> %s", - listener, mPluginMap.get(listener))); + synchronized (this) { + pw.println(String.format(" plugin map (%d):", mPluginMap.size())); + for (PluginListener listener : mPluginMap.keySet()) { + pw.println(String.format(" %s -> %s", + listener, mPluginMap.get(listener))); + } } } @@ -418,8 +432,10 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage // We couldn't find any plugins involved in this crash, just to be safe // disable all the plugins, so we can be sure that SysUI is running as // best as possible. - for (PluginInstanceManager manager : mPluginMap.values()) { - disabledAny |= manager.disableAll(); + synchronized (this) { + for (PluginInstanceManager manager : mPluginMap.values()) { + disabledAny |= manager.disableAll(); + } } } if (disabledAny) { @@ -433,9 +449,11 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage private boolean checkStack(Throwable throwable) { if (throwable == null) return false; boolean disabledAny = false; - for (StackTraceElement element : throwable.getStackTrace()) { - for (PluginInstanceManager manager : mPluginMap.values()) { - disabledAny |= manager.checkAndDisable(element.getClassName()); + synchronized (this) { + for (StackTraceElement element : throwable.getStackTrace()) { + for (PluginInstanceManager manager : mPluginMap.values()) { + disabledAny |= manager.checkAndDisable(element.getClassName()); + } } } return disabledAny | checkStack(throwable.getCause()); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java index b2c79a4c0a32..e106c657109d 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java @@ -52,7 +52,11 @@ public class TaskKeyLruCache<V> extends TaskKeyCache<V> { if (mEvictionCallback != null) { mEvictionCallback.onEntryEvicted(mKeys.get(taskId)); } - mKeys.remove(taskId); + + // Only remove from mKeys on cache remove, not a cache update. + if (newV == null) { + mKeys.remove(taskId); + } } }; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java index cc7863c0113b..c732584eddfc 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java @@ -80,18 +80,25 @@ public class QuickStepContract { public static final int SYSUI_STATE_HOME_DISABLED = 1 << 8; // The keyguard is showing, but occluded public static final int SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED = 1 << 9; + // The search feature is disabled (either by SUW/SysUI/device policy) + public static final int SYSUI_STATE_SEARCH_DISABLED = 1 << 10; + // The notification panel is expanded and interactive (either locked or unlocked), and the + // quick settings is not expanded + public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11; @Retention(RetentionPolicy.SOURCE) @IntDef({SYSUI_STATE_SCREEN_PINNING, SYSUI_STATE_NAV_BAR_HIDDEN, SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED, + SYSUI_STATE_QUICK_SETTINGS_EXPANDED, SYSUI_STATE_BOUNCER_SHOWING, SYSUI_STATE_A11Y_BUTTON_CLICKABLE, SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING, SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED, SYSUI_STATE_OVERVIEW_DISABLED, - SYSUI_STATE_HOME_DISABLED + SYSUI_STATE_HOME_DISABLED, + SYSUI_STATE_SEARCH_DISABLED }) public @interface SystemUiStateFlags {} @@ -100,8 +107,10 @@ public class QuickStepContract { str.add((flags & SYSUI_STATE_SCREEN_PINNING) != 0 ? "screen_pinned" : ""); str.add((flags & SYSUI_STATE_OVERVIEW_DISABLED) != 0 ? "overview_disabled" : ""); str.add((flags & SYSUI_STATE_HOME_DISABLED) != 0 ? "home_disabled" : ""); + str.add((flags & SYSUI_STATE_SEARCH_DISABLED) != 0 ? "search_disabled" : ""); str.add((flags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0 ? "navbar_hidden" : ""); str.add((flags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0 ? "notif_visible" : ""); + str.add((flags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) != 0 ? "qs_visible" : ""); str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) != 0 ? "keygrd_visible" : ""); str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0 ? "keygrd_occluded" : ""); @@ -150,10 +159,13 @@ public class QuickStepContract { * disabled. */ public static boolean isAssistantGestureDisabled(int sysuiStateFlags) { - // Disable when in screen pinning, immersive, the bouncer is showing + // Disable when in quick settings, screen pinning, immersive, the bouncer is showing, + // or search is disabled int disableFlags = SYSUI_STATE_SCREEN_PINNING | SYSUI_STATE_NAV_BAR_HIDDEN - | SYSUI_STATE_BOUNCER_SHOWING; + | SYSUI_STATE_BOUNCER_SHOWING + | SYSUI_STATE_SEARCH_DISABLED + | SYSUI_STATE_QUICK_SETTINGS_EXPANDED; if ((sysuiStateFlags & disableFlags) != 0) { return true; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java index d2fe5cd9ef64..2ef042210e67 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java @@ -91,6 +91,7 @@ public class RecentsAnimationControllerCompat { } } + @Deprecated public void setCancelWithDeferredScreenshot(boolean screenshot) { try { mAnimationController.setCancelWithDeferredScreenshot(screenshot); @@ -99,6 +100,14 @@ public class RecentsAnimationControllerCompat { } } + public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) { + try { + mAnimationController.setDeferCancelUntilNextTransition(defer, screenshot); + } catch (RemoteException e) { + Log.e(TAG, "Failed to set deferred cancel with screenshot", e); + } + } + public void cleanupScreenshot() { try { mAnimationController.cleanupScreenshot(); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentTaskInfoCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskInfoCompat.java index a5299038d3a9..326c2aa37175 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentTaskInfoCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskInfoCompat.java @@ -17,29 +17,32 @@ package com.android.systemui.shared.system; import android.app.ActivityManager; +import android.app.TaskInfo; import android.content.ComponentName; -public class RecentTaskInfoCompat { +public class TaskInfoCompat { - private ActivityManager.RecentTaskInfo mInfo; + public static int getUserId(TaskInfo info) { + return info.userId; + } - public RecentTaskInfoCompat(ActivityManager.RecentTaskInfo info) { - mInfo = info; + public static int getActivityType(TaskInfo info) { + return info.configuration.windowConfiguration.getActivityType(); } - public int getUserId() { - return mInfo.userId; + public static int getWindowingMode(TaskInfo info) { + return info.configuration.windowConfiguration.getWindowingMode(); } - public boolean supportsSplitScreenMultiWindow() { - return mInfo.supportsSplitScreenMultiWindow; + public static boolean supportsSplitScreenMultiWindow(TaskInfo info) { + return info.supportsSplitScreenMultiWindow; } - public ComponentName getTopActivity() { - return mInfo.topActivity; + public static ComponentName getTopActivity(TaskInfo info) { + return info.topActivity; } - public ActivityManager.TaskDescription getTaskDescription() { - return mInfo.taskDescription; + public static ActivityManager.TaskDescription getTaskDescription(TaskInfo info) { + return info.taskDescription; } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 2483192eb04e..5097216a7405 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -584,6 +584,9 @@ public class KeyguardClockSwitch extends RelativeLayout { @Override public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { + if (!sceneRoot.isShown()) { + return null; + } final float cutoff = mCutoff; final int startVisibility = View.INVISIBLE; final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY); @@ -596,6 +599,9 @@ public class KeyguardClockSwitch extends RelativeLayout { @Override public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { + if (!sceneRoot.isShown()) { + return null; + } final float cutoff = 1f - mCutoff; final int startVisibility = View.VISIBLE; final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 4ad262fee520..8059dcf33df7 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -269,7 +269,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe */ private void updateBiometricRetry() { SecurityMode securityMode = getSecurityMode(); - mSwipeUpToRetry = mUnlockMethodCache.isUnlockingWithFacePossible() + mSwipeUpToRetry = mUnlockMethodCache.isFaceAuthEnabled() && securityMode != SecurityMode.SimPin && securityMode != SecurityMode.SimPuk && securityMode != SecurityMode.None; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index e219e24a8944..af4e61b3f6bc 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -89,6 +89,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe private final HashMap<View, PendingIntent> mClickActions; private final ActivityStarter mActivityStarter; private final ConfigurationController mConfigurationController; + private final LayoutTransition mLayoutTransition; private Uri mKeyguardSliceUri; @VisibleForTesting TextView mTitle; @@ -126,16 +127,16 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe mActivityStarter = activityStarter; mConfigurationController = configurationController; - LayoutTransition transition = new LayoutTransition(); - transition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2); - transition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION); - transition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 2); - transition.disableTransitionType(LayoutTransition.CHANGE_APPEARING); - transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); - transition.setInterpolator(LayoutTransition.APPEARING, Interpolators.FAST_OUT_SLOW_IN); - transition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT); - transition.setAnimateParentHierarchy(false); - setLayoutTransition(transition); + mLayoutTransition = new LayoutTransition(); + mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2); + mLayoutTransition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION); + mLayoutTransition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 2); + mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING); + mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); + mLayoutTransition.setInterpolator(LayoutTransition.APPEARING, + Interpolators.FAST_OUT_SLOW_IN); + mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT); + mLayoutTransition.setAnimateParentHierarchy(false); } @Override @@ -174,6 +175,12 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe mConfigurationController.removeCallback(this); } + @Override + public void onVisibilityAggregated(boolean isVisible) { + super.onVisibilityAggregated(isVisible); + setLayoutTransition(isVisible ? mLayoutTransition : null); + } + /** * Returns whether the current visible slice has a title/header. */ @@ -419,6 +426,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe * their desired positions. */ private final Animation.AnimationListener mKeepAwakeListener; + private LayoutTransition mLayoutTransition; private float mDarkAmount; public Row(Context context) { @@ -440,33 +448,41 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe @Override protected void onFinishInflate() { - LayoutTransition transition = new LayoutTransition(); - transition.setDuration(DEFAULT_ANIM_DURATION); + mLayoutTransition = new LayoutTransition(); + mLayoutTransition.setDuration(DEFAULT_ANIM_DURATION); PropertyValuesHolder left = PropertyValuesHolder.ofInt("left", 0, 1); PropertyValuesHolder right = PropertyValuesHolder.ofInt("right", 0, 1); ObjectAnimator changeAnimator = ObjectAnimator.ofPropertyValuesHolder((Object) null, left, right); - transition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeAnimator); - transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeAnimator); - transition.setInterpolator(LayoutTransition.CHANGE_APPEARING, + mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeAnimator); + mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeAnimator); + mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_APPEARING, Interpolators.ACCELERATE_DECELERATE); - transition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING, + mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING, Interpolators.ACCELERATE_DECELERATE); - transition.setStartDelay(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION); - transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, DEFAULT_ANIM_DURATION); + mLayoutTransition.setStartDelay(LayoutTransition.CHANGE_APPEARING, + DEFAULT_ANIM_DURATION); + mLayoutTransition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, + DEFAULT_ANIM_DURATION); ObjectAnimator appearAnimator = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f); - transition.setAnimator(LayoutTransition.APPEARING, appearAnimator); - transition.setInterpolator(LayoutTransition.APPEARING, Interpolators.ALPHA_IN); + mLayoutTransition.setAnimator(LayoutTransition.APPEARING, appearAnimator); + mLayoutTransition.setInterpolator(LayoutTransition.APPEARING, Interpolators.ALPHA_IN); ObjectAnimator disappearAnimator = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f); - transition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT); - transition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 4); - transition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnimator); + mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING, + Interpolators.ALPHA_OUT); + mLayoutTransition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 4); + mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnimator); - transition.setAnimateParentHierarchy(false); - setLayoutTransition(transition); + mLayoutTransition.setAnimateParentHierarchy(false); + } + + @Override + public void onVisibilityAggregated(boolean isVisible) { + super.onVisibilityAggregated(isVisible); + setLayoutTransition(isVisible ? mLayoutTransition : null); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index fd618b05f348..4e7b15715243 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1783,13 +1783,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { && mFpm.getEnrolledFingerprints(userId).size() > 0; } + private boolean isUnlockWithFacePossible(int userId) { + return isFaceAuthEnabledForUser(userId) && !isFaceDisabled(userId); + } + /** * If face hardware is available, user has enrolled and enabled auth via setting. - * Not considering encryption or lock down state. */ - public boolean isUnlockWithFacePossible(int userId) { + public boolean isFaceAuthEnabledForUser(int userId) { return mFaceManager != null && mFaceManager.isHardwareDetected() - && !isFaceDisabled(userId) && mFaceManager.hasEnrolledTemplates(userId) && mFaceSettingEnabledForUser.get(userId); } diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index c9d4957494e4..bd91333100bd 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -47,7 +47,7 @@ public class ImageWallpaper extends WallpaperService { // This is to avoid destroying then recreating render context in a very short time. private static final int DELAY_FINISH_RENDERING = 1000; private static final int INTERVAL_WAIT_FOR_RENDERING = 100; - private static final int PATIENCE_WAIT_FOR_RENDERING = 5; + private static final int PATIENCE_WAIT_FOR_RENDERING = 10; private HandlerThread mWorker; @Override @@ -124,10 +124,10 @@ public class ImageWallpaper extends WallpaperService { @Override public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) { - long duration = mNeedTransition || animationDuration != 0 ? animationDuration : 0; + if (!mNeedTransition) return; mWorker.getThreadHandler().post( - () -> mRenderer.updateAmbientMode(inAmbientMode, duration)); - if (inAmbientMode && duration == 0) { + () -> mRenderer.updateAmbientMode(inAmbientMode, animationDuration)); + if (inAmbientMode && animationDuration == 0) { // This means that we are transiting from home to aod, to avoid // race condition between window visibility and transition, // we don't return until the transition is finished. See b/136643341. diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java index 4285af08e734..c4c0fd6da124 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemBars.java +++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java @@ -46,6 +46,13 @@ public class SystemBars extends SystemUI { } } + @Override + public void onBootCompleted() { + if (mStatusBar != null) { + mStatusBar.onBootCompleted(); + } + } + private void createStatusBarFromConfig() { if (DEBUG) Log.d(TAG, "createStatusBarFromConfig"); final String clsName = mContext.getString(R.string.config_statusBarComponent); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java index a5857df8ba5a..ce67577ea483 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java @@ -111,6 +111,9 @@ public abstract class BiometricDialogView extends LinearLayout { protected boolean mRequireConfirmation; private int mUserId; // used to determine if we should show work background + private boolean mCompletedAnimatingIn; + private boolean mPendingDismissDialog; + protected abstract int getHintStringResourceId(); protected abstract int getAuthenticatedAccessibilityResourceId(); protected abstract int getIconDescriptionResourceId(); @@ -332,6 +335,7 @@ public abstract class BiometricDialogView extends LinearLayout { mDialog.setAlpha(1.0f); mDialog.setTranslationY(0); mLayout.setAlpha(1.0f); + mCompletedAnimatingIn = true; } else { // Dim the background and slide the dialog up mDialog.setTranslationY(mAnimationTranslationOffset); @@ -352,6 +356,12 @@ public abstract class BiometricDialogView extends LinearLayout { } public void startDismiss() { + if (!mCompletedAnimatingIn) { + Log.w(TAG, "startDismiss(): waiting for onDialogAnimatedIn"); + mPendingDismissDialog = true; + return; + } + mAnimatingAway = true; // This is where final cleanup should occur. @@ -499,6 +509,13 @@ public abstract class BiometricDialogView extends LinearLayout { } public void onDialogAnimatedIn() { + mCompletedAnimatingIn = true; + + if (mPendingDismissDialog) { + Log.d(TAG, "onDialogAnimatedIn(): mPendingDismissDialog=true, dismissing now"); + startDismiss(); + mPendingDismissDialog = false; + } } public void restoreState(Bundle bundle) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java index 729242e3144f..ae6cb5ce23d3 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java @@ -460,6 +460,7 @@ public class FaceDialogView extends BiometricDialogView { @Override public void onDialogAnimatedIn() { + super.onDialogAnimatedIn(); mDialogAnimatedIn = true; mIconController.startPulsing(); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java index cee01a4d3048..ce82bbfb1512 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java @@ -50,6 +50,8 @@ public class BrightLineFalsingManager implements FalsingManager { private boolean mSessionStarted; private MetricsLogger mMetricsLogger; private int mIsFalseTouchCalls; + private boolean mShowingAod; + private boolean mScreenOn; private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor(); @@ -105,10 +107,12 @@ public class BrightLineFalsingManager implements FalsingManager { } private void sessionStart() { - logDebug("Starting Session"); - mSessionStarted = true; - registerSensors(); - mClassifiers.forEach(FalsingClassifier::onSessionStarted); + if (!mSessionStarted && !mShowingAod && mScreenOn) { + logDebug("Starting Session"); + mSessionStarted = true; + registerSensors(); + mClassifiers.forEach(FalsingClassifier::onSessionStarted); + } } private void sessionEnd() { @@ -172,6 +176,7 @@ public class BrightLineFalsingManager implements FalsingManager { mMetricsLogger.histogram(FALSING_SUCCESS, mIsFalseTouchCalls); mIsFalseTouchCalls = 0; } + sessionEnd(); } @Override @@ -180,6 +185,7 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void setShowingAod(boolean showingAod) { + mShowingAod = showingAod; if (showingAod) { sessionEnd(); } else { @@ -264,7 +270,7 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void onScreenOnFromTouch() { - sessionStart(); + onScreenTurningOn(); } @Override @@ -286,11 +292,13 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void onScreenTurningOn() { + mScreenOn = true; sessionStart(); } @Override public void onScreenOff() { + mScreenOn = false; sessionEnd(); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index ae6dac59b2f5..07dd2cd77043 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -77,8 +77,10 @@ public interface DozeHost { interface Callback { /** * Called when a high priority notification is added. + * @param onPulseSuppressedListener A listener that is invoked if the pulse is being + * supressed. */ - default void onNotificationAlerted() {} + default void onNotificationAlerted(Runnable onPulseSuppressedListener) {} /** * Called when battery state or power save mode changes. diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 8ef01e8d608e..2ca85c074a89 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -106,22 +106,31 @@ public class DozeTriggers implements DozeMachine.Part { mDockManager = dockManager; } - private void onNotification() { + private void onNotification(Runnable onPulseSuppressedListener) { if (DozeMachine.DEBUG) { Log.d(TAG, "requestNotificationPulse"); } if (!sWakeDisplaySensorState) { Log.d(TAG, "Wake display false. Pulse denied."); + runIfNotNull(onPulseSuppressedListener); return; } mNotificationPulseTime = SystemClock.elapsedRealtime(); if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) { + runIfNotNull(onPulseSuppressedListener); return; } - requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */); + requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */, + onPulseSuppressedListener); DozeLog.traceNotificationPulse(mContext); } + private static void runIfNotNull(Runnable runnable) { + if (runnable != null) { + runnable.run(); + } + } + private void proximityCheckThenCall(IntConsumer callback, boolean alreadyPerformedProxCheck, int reason) { @@ -158,10 +167,11 @@ public class DozeTriggers implements DozeMachine.Part { if (isWakeDisplay) { onWakeScreen(wakeEvent, mMachine.isExecutingTransition() ? null : mMachine.getState()); } else if (isLongPress) { - requestPulse(pulseReason, sensorPerformedProxCheck); + requestPulse(pulseReason, sensorPerformedProxCheck, null /* onPulseSupressedListener */); } else if (isWakeLockScreen) { if (wakeEvent) { - requestPulse(pulseReason, sensorPerformedProxCheck); + requestPulse(pulseReason, sensorPerformedProxCheck, + null /* onPulseSupressedListener */); } } else { proximityCheckThenCall((result) -> { @@ -340,7 +350,8 @@ public class DozeTriggers implements DozeMachine.Part { } } - private void requestPulse(final int reason, boolean performedProxCheck) { + private void requestPulse(final int reason, boolean performedProxCheck, + Runnable onPulseSuppressedListener) { Assert.isMainThread(); mDozeHost.extendPulse(reason); @@ -357,6 +368,7 @@ public class DozeTriggers implements DozeMachine.Part { DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(), mDozeHost.isPulsingBlocked()); } + runIfNotNull(onPulseSuppressedListener); return; } @@ -365,6 +377,7 @@ public class DozeTriggers implements DozeMachine.Part { if (result == ProximityCheck.RESULT_NEAR) { // in pocket, abort pulse mPulsePending = false; + runIfNotNull(onPulseSuppressedListener); } else { // not in pocket, continue pulsing continuePulseRequest(reason); @@ -482,7 +495,8 @@ public class DozeTriggers implements DozeMachine.Part { public void onReceive(Context context, Intent intent) { if (PULSE_ACTION.equals(intent.getAction())) { if (DozeMachine.DEBUG) Log.d(TAG, "Received pulse intent"); - requestPulse(DozeLog.PULSE_REASON_INTENT, false /* performedProxCheck */); + requestPulse(DozeLog.PULSE_REASON_INTENT, false, /* performedProxCheck */ + null /* onPulseSupressedListener */); } if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) { mMachine.requestState(DozeMachine.State.FINISH); @@ -532,8 +546,8 @@ public class DozeTriggers implements DozeMachine.Part { private DozeHost.Callback mHostCallback = new DozeHost.Callback() { @Override - public void onNotificationAlerted() { - onNotification(); + public void onNotificationAlerted(Runnable onPulseSuppressedListener) { + onNotification(onPulseSuppressedListener); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java index 45e97b38d87e..b154e66a846e 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java @@ -65,7 +65,7 @@ class ImageRevealHelper { @Override public void onAnimationStart(Animator animation) { if (mRevealListener != null) { - mRevealListener.onRevealStart(); + mRevealListener.onRevealStart(true /* animate */); } } }); @@ -73,7 +73,7 @@ class ImageRevealHelper { private void animate() { mAnimator.cancel(); - mAnimator.setFloatValues(mReveal, !mAwake ? MIN_REVEAL : MAX_REVEAL); + mAnimator.setFloatValues(mReveal, mAwake ? MAX_REVEAL : MIN_REVEAL); mAnimator.start(); } @@ -84,12 +84,11 @@ class ImageRevealHelper { void updateAwake(boolean awake, long duration) { mAwake = awake; mAnimator.setDuration(duration); - if (!mAwake && duration == 0) { - // We are transiting from home to aod, - // since main thread is waiting for rendering finished, we only need draw - // the last state directly, which is a black screen. - mReveal = MIN_REVEAL; - mRevealListener.onRevealStart(); + if (duration == 0) { + // We are transiting from home to aod or aod to home directly, + // we don't need to do transition in these cases. + mReveal = mAwake ? MAX_REVEAL : MIN_REVEAL; + mRevealListener.onRevealStart(false /* animate */); mRevealListener.onRevealStateChanged(); mRevealListener.onRevealEnd(); } else { @@ -110,7 +109,7 @@ class ImageRevealHelper { /** * Called back while reveal starts. */ - void onRevealStart(); + void onRevealStart(boolean animate); /** * Called back while reveal ends. diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java index 93d8dd6146a6..7b22a49fc88a 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java @@ -24,6 +24,7 @@ import static android.opengl.GLES20.glViewport; import android.app.WallpaperManager; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Rect; import android.util.Log; @@ -70,7 +71,14 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, DisplayInfo displayInfo = new DisplayInfo(); WindowManager wm = context.getSystemService(WindowManager.class); wm.getDefaultDisplay().getDisplayInfo(displayInfo); - mScissor = new Rect(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); + + // We only do transition in portrait currently, b/137962047. + int orientation = context.getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + mScissor = new Rect(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); + } else { + mScissor = new Rect(0, 0, displayInfo.logicalHeight, displayInfo.logicalWidth); + } mProxy = proxy; mProgram = new ImageGLProgram(context); @@ -179,20 +187,24 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, } @Override - public void onRevealStart() { - mScissorMode = true; - // Use current display area of texture. - mWallpaper.adjustTextureCoordinates(mSurfaceSize, mScissor, mXOffset, mYOffset); + public void onRevealStart(boolean animate) { + if (animate) { + mScissorMode = true; + // Use current display area of texture. + mWallpaper.adjustTextureCoordinates(mSurfaceSize, mScissor, mXOffset, mYOffset); + } mProxy.preRender(); } @Override public void onRevealEnd() { - mScissorMode = false; - // reset texture coordinates to use full texture. - mWallpaper.adjustTextureCoordinates(null, null, 0, 0); - // We need draw full texture back before finishing render. - mProxy.requestRender(); + if (mScissorMode) { + mScissorMode = false; + // reset texture coordinates to use full texture. + mWallpaper.adjustTextureCoordinates(null, null, 0, 0); + // We need draw full texture back before finishing render. + mProxy.requestRender(); + } mProxy.postRender(); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java index 5136682bb292..48f32cf04fb2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java @@ -52,6 +52,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.NextAlarmController; @@ -62,7 +63,6 @@ import com.android.systemui.util.wakelock.SettableWakeLock; import com.android.systemui.util.wakelock.WakeLock; import java.util.Date; -import java.util.HashSet; import java.util.Locale; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -128,6 +128,7 @@ public class KeyguardSliceProvider extends SliceProvider implements private CharSequence mMediaTitle; private CharSequence mMediaArtist; protected boolean mDozing; + private int mStatusBarState; private boolean mMediaIsVisible; /** @@ -231,7 +232,11 @@ public class KeyguardSliceProvider extends SliceProvider implements protected boolean needsMediaLocked() { boolean keepWhenAwake = mKeyguardBypassController != null && mKeyguardBypassController.getBypassEnabled() && mDozeParameters.getAlwaysOn(); - return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake); + // Show header if music is playing and the status bar is in the shade state. This way, an + // animation isn't necessary when pressing power and transitioning to AOD. + boolean keepWhenShade = mStatusBarState == StatusBarState.SHADE && mMediaIsVisible; + return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake + || keepWhenShade); } protected void addMediaLocked(ListBuilder listBuilder) { @@ -458,7 +463,7 @@ public class KeyguardSliceProvider extends SliceProvider implements synchronized (this) { boolean nextVisible = NotificationMediaManager.isPlayingState(state); mHandler.removeCallbacksAndMessages(mMediaToken); - if (mMediaIsVisible && !nextVisible) { + if (mMediaIsVisible && !nextVisible && mStatusBarState != StatusBarState.SHADE) { // We need to delay this event for a few millis when stopping to avoid jank in the // animation. The media app might not send its update when buffering, and the slice // would end up without a header for 0.5 second. @@ -515,5 +520,14 @@ public class KeyguardSliceProvider extends SliceProvider implements @Override public void onStateChanged(int newState) { + final boolean notify; + synchronized (this) { + boolean needsMedia = needsMediaLocked(); + mStatusBarState = newState; + notify = needsMedia != needsMediaLocked(); + } + if (notify) { + notifyChange(); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java index a9896f51369c..822a6669bd5c 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java @@ -22,6 +22,8 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.ContentResolver; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; @@ -48,6 +50,7 @@ import com.android.systemui.R; import java.io.File; import java.io.IOException; +import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.text.SimpleDateFormat; @@ -158,19 +161,34 @@ public class RecordingService extends Service { case ACTION_STOP: stopRecording(); - // Move temp file to user directory - File recordDir = new File( - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), - RECORD_DIR); - recordDir.mkdirs(); - String fileName = new SimpleDateFormat("'screen-'yyyyMMdd-HHmmss'.mp4'") .format(new Date()); - Path path = new File(recordDir, fileName).toPath(); + ContentValues values = new ContentValues(); + values.put(MediaStore.Video.Media.DISPLAY_NAME, fileName); + values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4"); + values.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis()); + values.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis()); + + ContentResolver resolver = getContentResolver(); + Uri collectionUri = MediaStore.Video.Media.getContentUri( + MediaStore.VOLUME_EXTERNAL_PRIMARY); + Uri itemUri = resolver.insert(collectionUri, values); + + File recordDir = new File(getExternalFilesDir(Environment.DIRECTORY_MOVIES), + RECORD_DIR); + recordDir.mkdirs(); + Path path = new File(recordDir, fileName).toPath(); try { + // Move file out of temp directory Files.move(mTempFile.toPath(), path); - Notification notification = createSaveNotification(path); + + // Add to the mediastore + OutputStream os = resolver.openOutputStream(itemUri, "w"); + Files.copy(path, os); + os.close(); + + Notification notification = createSaveNotification(itemUri, path); notificationManager.notify(NOTIFICATION_ID, notification); } catch (IOException e) { e.printStackTrace(); @@ -352,13 +370,12 @@ public class RecordingService extends Service { notificationManager.notify(NOTIFICATION_ID, mRecordingNotificationBuilder.build()); } - private Notification createSaveNotification(Path path) { - Uri saveUri = FileProvider.getUriForFile(this, FILE_PROVIDER, path.toFile()); - Log.d(TAG, "Screen recording saved to " + path.toString()); + private Notification createSaveNotification(Uri uri, Path path) { + Log.d(TAG, "Screen recording saved to " + uri.toString() + ", " + path.toString()); Intent viewIntent = new Intent(Intent.ACTION_VIEW) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION) - .setDataAndType(saveUri, "video/mp4"); + .setDataAndType(uri, "video/mp4"); Notification.Action shareAction = new Notification.Action.Builder( Icon.createWithResource(this, R.drawable.ic_android), @@ -366,7 +383,7 @@ public class RecordingService extends Service { PendingIntent.getService( this, REQUEST_CODE, - getShareIntent(this, path.toString()), + getShareIntent(this, uri.toString()), PendingIntent.FLAG_UPDATE_CURRENT)) .build(); @@ -376,7 +393,7 @@ public class RecordingService extends Service { PendingIntent.getService( this, REQUEST_CODE, - getDeleteIntent(this, path.toString()), + getDeleteIntent(this, uri.toString()), PendingIntent.FLAG_UPDATE_CURRENT)) .build(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java index 0fe5f8a6af5a..4cc5b2144adc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java @@ -15,7 +15,6 @@ package com.android.systemui.statusbar; import android.content.pm.UserInfo; -import android.service.notification.StatusBarNotification; import android.util.SparseArray; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -58,7 +57,7 @@ public interface NotificationLockscreenUserManager { boolean shouldHideNotifications(int userId); boolean shouldHideNotifications(String key); - boolean shouldShowOnKeyguard(StatusBarNotification sbn); + boolean shouldShowOnKeyguard(NotificationEntry entry); boolean isAnyProfilePublicMode(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 4ea1ed5b9451..e08a5ae07bd8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -33,7 +33,6 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; -import android.service.notification.StatusBarNotification; import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -302,7 +301,7 @@ public class NotificationLockscreenUserManagerImpl implements Notification.VISIBILITY_SECRET; } - public boolean shouldShowOnKeyguard(StatusBarNotification sbn) { + public boolean shouldShowOnKeyguard(NotificationEntry entry) { if (getEntryManager() == null) { Log.wtf(TAG, "mEntryManager was null!", new Throwable()); return false; @@ -310,10 +309,10 @@ public class NotificationLockscreenUserManagerImpl implements boolean exceedsPriorityThreshold; if (NotificationUtils.useNewInterruptionModel(mContext) && hideSilentNotificationsOnLockscreen()) { - exceedsPriorityThreshold = getEntryManager().getNotificationData().isHighPriority(sbn); + exceedsPriorityThreshold = entry.isTopBucket(); } else { exceedsPriorityThreshold = - !getEntryManager().getNotificationData().isAmbient(sbn.getKey()); + !getEntryManager().getNotificationData().isAmbient(entry.key); } return mShowLockscreenNotifications && exceedsPriorityThreshold; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index f001561754aa..00a12a9e4409 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -17,6 +17,10 @@ package com.android.systemui.statusbar; import static com.android.systemui.Dependency.MAIN_HANDLER; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; +import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_FADING; +import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK; +import static com.android.systemui.statusbar.phone.BiometricUnlockController + .MODE_WAKE_AND_UNLOCK_PULSING; import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK; import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER; import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK; @@ -595,9 +599,11 @@ public class NotificationMediaManager implements Dumpable { boolean cannotAnimateDoze = shadeController != null && shadeController.isDozing() && !ScrimState.AOD.getAnimateChange(); - if (mBiometricUnlockController != null && mBiometricUnlockController.getMode() + boolean needsBypassFading = mKeyguardMonitor.isBypassFadingAnimation(); + if (((mBiometricUnlockController != null && mBiometricUnlockController.getMode() == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING - || hideBecauseOccluded || cannotAnimateDoze) { + || cannotAnimateDoze) && !needsBypassFading) + || hideBecauseOccluded) { // We are unlocking directly - no animation! mBackdrop.setVisibility(View.GONE); @@ -622,9 +628,7 @@ public class NotificationMediaManager implements Dumpable { }); if (mKeyguardMonitor.isKeyguardFadingAway()) { mBackdrop.animate() - // Make it disappear faster, as the focus should be on the activity - // behind. - .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2) + .setDuration(mKeyguardMonitor.getShortenedFadingAwayDuration()) .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay()) .setInterpolator(Interpolators.LINEAR) .start(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 22c91647d7f7..6e75c0375afc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -397,15 +397,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle int userId = entry.notification.getUserId(); boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup( entry.notification) && !entry.isRowRemoved(); - boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry - .notification); + boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry); if (!showOnKeyguard) { // min priority notifications should show if their summary is showing if (mGroupManager.isChildInGroupWithSummary(entry.notification)) { NotificationEntry summary = mGroupManager.getLogicalGroupSummary( entry.notification); - if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard( - summary.notification)) { + if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) { showOnKeyguard = true; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt index ea474ced7632..314dc04e574f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt @@ -21,6 +21,7 @@ import android.media.MediaMetadata import android.provider.Settings import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.NotificationMediaManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -40,6 +41,7 @@ class BypassHeadsUpNotifier @Inject constructor( private val bypassController: KeyguardBypassController, private val statusBarStateController: StatusBarStateController, private val headsUpManager: HeadsUpManagerPhone, + private val notificationLockscreenUserManager: NotificationLockscreenUserManager, private val mediaManager: NotificationMediaManager, tunerService: TunerService) : StatusBarStateController.StateListener, NotificationMediaManager.MediaListener { @@ -63,7 +65,7 @@ class BypassHeadsUpNotifier @Inject constructor( enabled = Settings.Secure.getIntForUser( context.contentResolver, Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING, - 1 /* default */, + 0 /* default */, KeyguardUpdateMonitor.getCurrentUser()) != 0 }, Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING) } @@ -79,9 +81,6 @@ class BypassHeadsUpNotifier @Inject constructor( if (!NotificationMediaManager.isPlayingState(state)) { newEntry = null } - if (newEntry?.isSensitive == true) { - newEntry = null - } currentMediaEntry = newEntry updateAutoHeadsUp(previous) updateAutoHeadsUp(currentMediaEntry) @@ -89,7 +88,7 @@ class BypassHeadsUpNotifier @Inject constructor( private fun updateAutoHeadsUp(entry: NotificationEntry?) { entry?.let { - val autoHeadsUp = it == currentMediaEntry && canAutoHeadsUp() + val autoHeadsUp = it == currentMediaEntry && canAutoHeadsUp(it) it.isAutoHeadsUp = autoHeadsUp if (autoHeadsUp) { headsUpManager.showNotification(it) @@ -97,11 +96,36 @@ class BypassHeadsUpNotifier @Inject constructor( } } + /** + * @return {@code true} if this entry be autoHeadsUpped right now. + */ + private fun canAutoHeadsUp(entry: NotificationEntry): Boolean { + if (!isAutoHeadsUpAllowed()) { + return false; + } + if (entry.isSensitive) { + // filter sensitive notifications + return false + } + if (!notificationLockscreenUserManager.shouldShowOnKeyguard(entry)) { + // filter notifications invisible on Keyguard + return false + } + if (!entryManager.notificationData.activeNotifications.contains(entry)) { + // filter notifications not the active list currently + return false + } + return true + } + override fun onStatePostChange() { updateAutoHeadsUp(currentMediaEntry) } - private fun canAutoHeadsUp() : Boolean { + /** + * @return {@code true} if autoHeadsUp is possible right now. + */ + private fun isAutoHeadsUpAllowed() : Boolean { if (!enabled) { return false } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index 6a3816c50330..6af1f5bca07f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -29,6 +29,7 @@ import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.HeadsUpManagerPhone import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.NotificationIconAreaController +import com.android.systemui.statusbar.phone.PanelExpansionListener import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener import javax.inject.Inject @@ -40,7 +41,8 @@ class NotificationWakeUpCoordinator @Inject constructor( private val mHeadsUpManagerPhone: HeadsUpManagerPhone, private val statusBarStateController: StatusBarStateController, private val bypassController: KeyguardBypassController) - : OnHeadsUpChangedListener, StatusBarStateController.StateListener { + : OnHeadsUpChangedListener, StatusBarStateController.StateListener, + PanelExpansionListener { private val mNotificationVisibility = object : FloatProperty<NotificationWakeUpCoordinator>("notificationVisibility") { @@ -64,7 +66,6 @@ class NotificationWakeUpCoordinator @Inject constructor( private var mVisibilityAnimator: ObjectAnimator? = null private var mVisibilityAmount = 0.0f private var mLinearVisibilityAmount = 0.0f - private var mWakingUp = false private val mEntrySetToClearWhenFinished = mutableSetOf<NotificationEntry>() private val mDozeParameters: DozeParameters private var pulseExpanding: Boolean = false @@ -73,6 +74,25 @@ class NotificationWakeUpCoordinator @Inject constructor( var fullyAwake: Boolean = false + var wakingUp = false + set(value) { + field = value + willWakeUp = false + if (value) { + if (mNotificationsVisible && !mNotificationsVisibleForExpansion + && !bypassController.bypassEnabled) { + // We're waking up while pulsing, let's make sure the animation looks nice + mStackScroller.wakeUpFromPulse(); + } + if (bypassController.bypassEnabled && !mNotificationsVisible) { + // Let's make sure our huns become visible once we are waking up in case + // they were blocked by the proximity sensor + updateNotificationVisibility(animate = shouldAnimateVisibility(), + increaseSpeed = false) + } + } + } + var willWakeUp = false set(value) { if (!value || mDozeAmount != 0.0f) { @@ -80,7 +100,9 @@ class NotificationWakeUpCoordinator @Inject constructor( } } + private var collapsedEnoughToHide: Boolean = false lateinit var iconAreaController : NotificationIconAreaController + var pulsing: Boolean = false set(value) { field = value @@ -102,7 +124,6 @@ class NotificationWakeUpCoordinator @Inject constructor( } } } - /** * True if we can show pulsing heads up notifications */ @@ -112,8 +133,12 @@ class NotificationWakeUpCoordinator @Inject constructor( var canShow = pulsing if (bypassController.bypassEnabled) { // We also allow pulsing on the lock screen! - canShow = canShow || (mWakingUp || willWakeUp || fullyAwake) + canShow = canShow || (wakingUp || willWakeUp || fullyAwake) && statusBarStateController.state == StatusBarState.KEYGUARD + // We want to hide the notifications when collapsed too much + if (collapsedEnoughToHide) { + canShow = false + } } return canShow } @@ -160,7 +185,7 @@ class NotificationWakeUpCoordinator @Inject constructor( wakeUpListeners.add(listener); } - fun removeFullyHiddenChangedListener(listener: WakeUpListener) { + fun removeListener(listener: WakeUpListener) { wakeUpListeners.remove(listener); } @@ -169,7 +194,7 @@ class NotificationWakeUpCoordinator @Inject constructor( var visible = mNotificationsVisibleForExpansion || mHeadsUpManagerPhone.hasNotifications() visible = visible && canShowPulsingHuns - if (!visible && mNotificationsVisible && (mWakingUp || willWakeUp) && mDozeAmount != 0.0f) { + if (!visible && mNotificationsVisible && (wakingUp || willWakeUp) && mDozeAmount != 0.0f) { // let's not make notifications invisible while waking up, otherwise the animation // is strange return; @@ -229,6 +254,18 @@ class NotificationWakeUpCoordinator @Inject constructor( this.state = newState } + override fun onPanelExpansionChanged(expansion: Float, tracking: Boolean) { + val collapsedEnough = expansion <= 0.9f + if (collapsedEnough != this.collapsedEnoughToHide) { + val couldShowPulsingHuns = canShowPulsingHuns; + this.collapsedEnoughToHide = collapsedEnough + if (couldShowPulsingHuns && !canShowPulsingHuns) { + updateNotificationVisibility(animate = true, increaseSpeed = true) + mHeadsUpManagerPhone.releaseAllImmediately() + } + } + } + private fun updateDozeAmountIfBypass(): Boolean { if (bypassController.bypassEnabled) { var amount = 1.0f; @@ -307,16 +344,6 @@ class NotificationWakeUpCoordinator @Inject constructor( return if (bypassController.bypassEnabled) 0.0f else overflow } - fun setWakingUp(wakingUp: Boolean) { - willWakeUp = false - mWakingUp = wakingUp - if (wakingUp && mNotificationsVisible && !mNotificationsVisibleForExpansion - && !bypassController.bypassEnabled) { - // We're waking up while pulsing, let's make sure the animation looks nice - mStackScroller.wakeUpFromPulse(); - } - } - override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) { var animate = shouldAnimateVisibility() if (!isHeadsUp) { @@ -325,7 +352,7 @@ class NotificationWakeUpCoordinator @Inject constructor( // if we animate, we see the shelf briefly visible. Instead we fully animate // the notification and its background out animate = false - } else if (!mWakingUp && !willWakeUp){ + } else if (!wakingUp && !willWakeUp){ // TODO: look that this is done properly and not by anyone else entry.setHeadsUpAnimatingAway(true) mEntrySetToClearWhenFinished.add(entry) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java index fca520fe0521..1ce493444e25 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java @@ -25,7 +25,6 @@ import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; -import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; @@ -108,10 +107,19 @@ public class NotificationData { boolean bSystemMax = bImportance >= NotificationManager.IMPORTANCE_HIGH && isSystemNotification(nb); - boolean isHeadsUp = a.getRow().isHeadsUp(); - if (isHeadsUp != b.getRow().isHeadsUp()) { - return isHeadsUp ? -1 : 1; - } else if (isHeadsUp) { + + boolean aHeadsUp = a.getRow().isHeadsUp(); + boolean bHeadsUp = b.getRow().isHeadsUp(); + + // HACK: This should really go elsewhere, but it's currently not straightforward to + // extract the comparison code and we're guaranteed to touch every element, so this is + // the best place to set the buckets for the moment. + a.setIsTopBucket(aHeadsUp || aMedia || aSystemMax || a.isHighPriority()); + b.setIsTopBucket(bHeadsUp || bMedia || bSystemMax || b.isHighPriority()); + + if (aHeadsUp != bHeadsUp) { + return aHeadsUp ? -1 : 1; + } else if (aHeadsUp) { // Provide consistent ranking with headsUpManager return mHeadsUpManager.compare(a, b); } else if (aMedia != bMedia) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index b19d2ca29c96..fe8854168288 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -173,9 +173,13 @@ public final class NotificationEntry { * the lock screen/status bar and in the top section in the shade. */ private boolean mHighPriority; + + private boolean mIsTopBucket; + private boolean mSensitive = true; private Runnable mOnSensitiveChangedListener; private boolean mAutoHeadsUp; + private boolean mPulseSupressed; public NotificationEntry(StatusBarNotification n) { this(n, null); @@ -224,6 +228,18 @@ public final class NotificationEntry { this.mHighPriority = highPriority; } + /** + * @return True if the notif should appear in the "top" or "important" section of notifications + * (as opposed to the "bottom" or "silent" section). This is usually the same as + * {@link #isHighPriority()}, but there are certain exceptions, such as media notifs. + */ + public boolean isTopBucket() { + return mIsTopBucket; + } + public void setIsTopBucket(boolean isTopBucket) { + mIsTopBucket = isTopBucket; + } + public boolean isBubble() { return (notification.getNotification().flags & FLAG_BUBBLE) != 0; } @@ -900,6 +916,14 @@ public final class NotificationEntry { mOnSensitiveChangedListener = listener; } + public boolean isPulseSuppressed() { + return mPulseSupressed; + } + + public void setPulseSuppressed(boolean suppressed) { + mPulseSupressed = suppressed; + } + /** Information about a suggestion that is being edited. */ public static class EditedSuggestionInfo { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java index d057a1d2f20b..48a82957bf1e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java @@ -349,7 +349,7 @@ public class NotificationContentInflater { } if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) { - result.newPublicView = builder.makePublicContentView(); + result.newPublicView = builder.makePublicContentView(isLowPriority); } result.packageContext = packageContext; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java index 212808dae8e3..15cc72c2d7a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java @@ -184,4 +184,6 @@ public interface NotificationListContainer extends ExpandableView.OnHeightChange default boolean containsView(View v) { return true; } + + default void setWillExpand(boolean willExpand) {}; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java index 170a4d570688..d119fb79e4c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java @@ -133,7 +133,7 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide if (child instanceof ExpandableNotificationRow && child.getVisibility() != View.GONE) { ExpandableNotificationRow row = (ExpandableNotificationRow) child; - if (!row.getEntry().isHighPriority()) { + if (!row.getEntry().isTopBucket()) { firstGentleNotifIndex = i; mFirstGentleNotif = row; break; @@ -248,7 +248,7 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide View child = mParent.getChildAt(i); if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) child; - if (!row.getEntry().isHighPriority()) { + if (!row.getEntry().isTopBucket()) { break; } else { lastChildBeforeGap = row; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index bec95201e4b2..18a51b9abd8c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -499,6 +499,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private boolean mAnimateBottomOnLayout; private float mLastSentAppear; private float mLastSentExpandedHeight; + private boolean mWillExpand; @Inject public NotificationStackScrollLayout( @@ -2549,13 +2550,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } return; } - int minTopPosition = 0; + int minTopPosition; NotificationSection lastSection = getLastVisibleSection(); boolean onKeyguard = mStatusBarState == StatusBarState.KEYGUARD; if (!onKeyguard) { minTopPosition = (int) (mTopPadding + mStackTranslation); } else if (lastSection == null) { minTopPosition = mTopPadding; + } else { + // The first sections could be empty while there could still be elements in later + // sections. The position of these first few sections is determined by the position of + // the first visible section. + NotificationSection firstVisibleSection = getFirstVisibleSection(); + firstVisibleSection.updateBounds(0 /* minTopPosition*/, 0 /* minBottomPosition */, + false /* shiftPulsingWithFirst */); + minTopPosition = firstVisibleSection.getBounds().top; } boolean shiftPulsingWithFirst = mHeadsUpManager.getAllEntries().count() <= 1 && (mAmbientState.isDozing() @@ -4398,6 +4407,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mStateAnimator.setShadeExpanded(isExpanded); mSwipeHelper.setIsExpanded(isExpanded); if (changed) { + mWillExpand = false; if (!mIsExpanded) { mGroupManager.collapseAllGroups(); mExpandHelper.cancelImmediately(); @@ -5046,7 +5056,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd if (mAnimationsEnabled && (isHeadsUp || mHeadsUpGoingAwayAnimationsAllowed)) { mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp)); mNeedsAnimation = true; - if (!mIsExpanded && !isHeadsUp) { + if (!mIsExpanded && !mWillExpand && !isHeadsUp) { row.setHeadsUpAnimatingAway(true); } requestChildrenUpdate(); @@ -5067,6 +5077,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd requestChildrenUpdate(); } + @Override + public void setWillExpand(boolean willExpand) { + mWillExpand = willExpand; + } + @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void setTrackingHeadsUp(ExpandableNotificationRow row) { mTrackingHeadsUp = row != null; @@ -5667,6 +5682,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd // The bottom might change because we're using the final actual height of the view mAnimateBottomOnLayout = true; } + // Let's update the footer once the notifications have been updated (in the next frame) + post(this::updateFooter); } public void setOnPulseHeightChangedListener(Runnable listener) { @@ -5737,7 +5754,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd currentIndex++; boolean beforeSpeedBump; if (mHighPriorityBeforeSpeedBump) { - beforeSpeedBump = row.getEntry().isHighPriority(); + beforeSpeedBump = row.getEntry().isTopBucket(); } else { beforeSpeedBump = !row.getEntry().ambient; } @@ -5795,9 +5812,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd case ROWS_ALL: return true; case ROWS_HIGH_PRIORITY: - return row.getEntry().isHighPriority(); + return row.getEntry().isTopBucket(); case ROWS_GENTLE: - return !row.getEntry().isHighPriority(); + return !row.getEntry().isTopBucket(); default: throw new IllegalArgumentException("Unknown selection: " + selection); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 94cd2cdaa9d3..41c6a7ba7848 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -445,14 +445,13 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { if (!mUpdateMonitor.isDeviceInteractive()) { if (!mStatusBarKeyguardViewManager.isShowing()) { return bypass ? MODE_WAKE_AND_UNLOCK : MODE_ONLY_WAKE; - } else if (mDozeScrimController.isPulsing() && unlockingAllowed) { + } else if (!unlockingAllowed) { + return bypass ? MODE_SHOW_BOUNCER : MODE_NONE; + } else if (mDozeScrimController.isPulsing()) { // Let's not wake-up to lock screen when not bypassing, otherwise the notification // would move as the user tried to tap it. return bypass ? MODE_WAKE_AND_UNLOCK_PULSING : MODE_NONE; } else { - if (!(mDozeScrimController.isPulsing() && !unlockingAllowed)) { - Log.wtf(TAG, "Face somehow arrived when the device was not interactive"); - } if (bypass) { // Wake-up fading out nicely return MODE_WAKE_AND_UNLOCK_PULSING; @@ -530,7 +529,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { mStatusBar.notifyBiometricAuthModeChanged(); } - private final WakefulnessLifecycle.Observer mWakefulnessObserver = + @VisibleForTesting + final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override public void onFinishedWakingUp() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java index 46dd5e62ddda..f53c4e8c818e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -35,6 +35,7 @@ import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.HeadsUpStatusBarView; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; @@ -48,7 +49,7 @@ import java.util.function.Consumer; * Controls the appearance of heads up notifications in the icon area and the header itself. */ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, - DarkIconDispatcher.DarkReceiver { + DarkIconDispatcher.DarkReceiver, NotificationWakeUpCoordinator.WakeUpListener { public static final int CONTENT_FADE_DURATION = 110; public static final int CONTENT_FADE_DELAY = 100; private final NotificationIconAreaController mNotificationIconAreaController; @@ -67,6 +68,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, private final KeyguardBypassController mBypassController; private final StatusBarStateController mStatusBarStateController; private final CommandQueue mCommandQueue; + private final NotificationWakeUpCoordinator mWakeUpCoordinator; @VisibleForTesting float mExpandedHeight; @VisibleForTesting @@ -95,9 +97,10 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, HeadsUpManagerPhone headsUpManager, View statusbarView, SysuiStatusBarStateController statusBarStateController, - KeyguardBypassController keyguardBypassController) { + KeyguardBypassController keyguardBypassController, + NotificationWakeUpCoordinator wakeUpCoordinator) { this(notificationIconAreaController, headsUpManager, statusBarStateController, - keyguardBypassController, + keyguardBypassController, wakeUpCoordinator, statusbarView.findViewById(R.id.heads_up_status_bar_view), statusbarView.findViewById(R.id.notification_stack_scroller), statusbarView.findViewById(R.id.notification_panel), @@ -112,6 +115,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, HeadsUpManagerPhone headsUpManager, StatusBarStateController stateController, KeyguardBypassController bypassController, + NotificationWakeUpCoordinator wakeUpCoordinator, HeadsUpStatusBarView headsUpStatusBarView, NotificationStackScrollLayout stackScroller, NotificationPanelView panelView, @@ -153,6 +157,8 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, }); mBypassController = bypassController; mStatusBarStateController = stateController; + mWakeUpCoordinator = wakeUpCoordinator; + wakeUpCoordinator.addListener(this); mCommandQueue = getComponent(headsUpStatusBarView.getContext(), CommandQueue.class); mKeyguardMonitor = Dependency.get(KeyguardMonitor.class); } @@ -161,6 +167,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, public void destroy() { mHeadsUpManager.removeListener(this); mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null); + mWakeUpCoordinator.removeListener(this); mPanelView.removeTrackingHeadsUpListener(mSetTrackingHeadsUp); mPanelView.removeVerticalTranslationListener(mUpdatePanelTranslation); mPanelView.setHeadsUpAppearanceController(null); @@ -289,6 +296,11 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, updateParentClipping(true /* shouldClip */); }); } + // Show the status bar icons when the view gets shown / hidden + if (mStatusBarStateController.getState() != StatusBarState.SHADE) { + mCommandQueue.recomputeDisableFlags( + mHeadsUpStatusBarView.getContext().getDisplayId(), false); + } } } @@ -362,10 +374,12 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, * @return if the heads up status bar view should be shown */ public boolean shouldBeVisible() { - boolean canShow = !mIsExpanded; + boolean notificationsShown = !mWakeUpCoordinator.getNotificationsFullyHidden(); + boolean canShow = !mIsExpanded && notificationsShown; if (mBypassController.getBypassEnabled() && (mStatusBarStateController.getState() == StatusBarState.KEYGUARD - || mKeyguardMonitor.isKeyguardGoingAway())) { + || mKeyguardMonitor.isKeyguardGoingAway()) + && notificationsShown) { canShow = true; } return canShow && mHeadsUpManager.hasPinnedHeadsUp(); @@ -377,15 +391,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, updateHeader(entry); } - @Override - public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { - if (mStatusBarStateController.getState() != StatusBarState.SHADE) { - // Show the status bar icons when the pinned mode changes - mCommandQueue.recomputeDisableFlags( - mHeadsUpStatusBarView.getContext().getDisplayId(), false); - } - } - public void setAppearFraction(float expandedHeight, float appearFraction) { boolean changed = expandedHeight != mExpandedHeight; mExpandedHeight = expandedHeight; @@ -451,4 +456,9 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, mAppearFraction = oldController.mAppearFraction; } } + + @Override + public void onFullyHiddenChanged(boolean isFullyHidden) { + updateTopEntry(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index d6f8a606af55..c4d346ccaefb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -170,7 +170,7 @@ public class KeyguardBouncer { // Split up the work over multiple frames. DejankUtils.removeCallbacks(mResetRunnable); - if (mUnlockMethodCache.isUnlockingWithFacePossible() && !needsFullscreenBouncer() + if (mUnlockMethodCache.isFaceAuthEnabled() && !needsFullscreenBouncer() && !mKeyguardUpdateMonitor.userNeedsStrongAuth()) { mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY); } else { @@ -207,14 +207,12 @@ public class KeyguardBouncer { * @see #onFullyShown() */ private void onFullyHidden() { - if (!mShowingSoon) { - cancelShowRunnable(); - if (mRoot != null) { - mRoot.setVisibility(View.INVISIBLE); - } - mFalsingManager.onBouncerHidden(); - DejankUtils.postAfterTraversal(mResetRunnable); + cancelShowRunnable(); + if (mRoot != null) { + mRoot.setVisibility(View.INVISIBLE); } + mFalsingManager.onBouncerHidden(); + DejankUtils.postAfterTraversal(mResetRunnable); } private final Runnable mShowRunnable = new Runnable() { @@ -349,7 +347,7 @@ public class KeyguardBouncer { * {@link #show(boolean)} was called but we're not showing yet, or being dragged. */ public boolean inTransit() { - return mShowingSoon || mExpansion != EXPANSION_HIDDEN; + return mShowingSoon || mExpansion != EXPANSION_HIDDEN && mExpansion != EXPANSION_VISIBLE; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index 0aec2b12fa92..70d3bff9b822 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -47,7 +47,7 @@ class KeyguardBypassController { * If face unlock dismisses the lock screen or keeps user on keyguard for the current user. */ var bypassEnabled: Boolean = false - get() = field && unlockMethodCache.isUnlockingWithFacePossible + get() = field && unlockMethodCache.isFaceAuthEnabled private set var bouncerShowing: Boolean = false diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java index 1360a084207b..c9c80d464b46 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -217,7 +217,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange mConfigurationController.removeCallback(this); mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); mKeyguardMonitor.removeCallback(mKeyguardMonitorCallback); - mWakeUpCoordinator.removeFullyHiddenChangedListener(this); + mWakeUpCoordinator.removeListener(this); mUnlockMethodCache.removeListener(this); if (mDockManager != null) { mDockManager.removeListener(mDockEventListener); @@ -323,14 +323,24 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange } updateDarkTint(); + updateIconVisibility(); + updateClickability(); + + return true; + } + + /** + * Update the icon visibility + * @return true if the visibility changed + */ + private boolean updateIconVisibility() { boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked); boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance; if (mBypassController.getBypassEnabled() && !mBouncerShowingScrimmed) { - if (mHeadsUpManager.isHeadsUpGoingAway() - || mHeadsUpManager.hasPinnedHeadsUp() - || (mStatusBarStateController.getState() == StatusBarState.KEYGUARD - && !mWakeUpCoordinator.getNotificationsFullyHidden())) { + if ((mHeadsUpManager.isHeadsUpGoingAway() || mHeadsUpManager.hasPinnedHeadsUp()) + && mStatusBarStateController.getState() == StatusBarState.KEYGUARD + && !mWakeUpCoordinator.getNotificationsFullyHidden()) { invisible = true; } } @@ -349,10 +359,9 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange .setDuration(233) .start(); } + return true; } - updateClickability(); - - return true; + return false; } private boolean canBlockUpdates() { @@ -440,7 +449,10 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange @Override public void onFullyHiddenChanged(boolean isFullyHidden) { if (mBypassController.getBypassEnabled()) { - update(); + boolean changed = updateIconVisibility(); + if (changed) { + update(); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 22e3edb2bbd8..081e29381a65 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -21,7 +21,9 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SEARCH_DISABLED; import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; @@ -706,7 +708,7 @@ public class NavigationBarView extends FrameLayout implements } } - public void onPanelExpandedChange() { + public void onStatusBarPanelStateChanged() { updateSlippery(); updateSystemUiStateFlags(); } @@ -719,9 +721,13 @@ public class NavigationBarView extends FrameLayout implements (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0, displayId); mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_HOME_DISABLED, (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0, displayId); + mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_SEARCH_DISABLED, + (mDisabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0, displayId); if (mPanelView != null) { mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED, mPanelView.isFullyExpanded() && !mPanelView.isInSettings(), displayId); + mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED, + mPanelView.isInSettings(), displayId); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java index 0fe12943614c..4f7af58094ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java @@ -53,8 +53,8 @@ public class NavigationHandle extends View implements ButtonInterface { final int dualToneLightTheme = Utils.getThemeAttr(context, R.attr.lightIconTheme); Context lightContext = new ContextThemeWrapper(context, dualToneLightTheme); Context darkContext = new ContextThemeWrapper(context, dualToneDarkTheme); - mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor); - mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor); + mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.homeHandleColor); + mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.homeHandleColor); mPaint.setAntiAlias(true); setFocusable(false); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java index 64fef55a21d3..1df9411019d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java @@ -32,8 +32,6 @@ import static com.android.systemui.shared.system.QuickStepContract.ACTION_ENABLE import static com.android.systemui.shared.system.QuickStepContract.ACTION_ENABLE_GESTURE_NAV_RESULT; import static com.android.systemui.shared.system.QuickStepContract.EXTRA_RESULT_INTENT; -import android.app.Notification; -import android.app.NotificationManager; import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; @@ -42,7 +40,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.om.IOverlayManager; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.ApkAssets; import android.os.PatternMatcher; @@ -52,16 +49,13 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Secure; -import android.text.TextUtils; import android.util.Log; import android.util.SparseBooleanArray; import com.android.systemui.Dumpable; -import com.android.systemui.R; import com.android.systemui.UiOffloadThread; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.statusbar.policy.DeviceProvisionedController; -import com.android.systemui.util.NotificationChannels; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -80,11 +74,6 @@ public class NavigationModeController implements Dumpable { private static final String TAG = NavigationModeController.class.getSimpleName(); private static final boolean DEBUG = false; - private static final int SYSTEM_APP_MASK = - ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; - static final String SHARED_PREFERENCES_NAME = "navigation_mode_controller_preferences"; - static final String PREFS_SWITCHED_FROM_GESTURE_NAV_KEY = "switched_from_gesture_nav"; - public interface ModeChangedListener { void onNavigationModeChanged(int mode); } @@ -100,8 +89,6 @@ public class NavigationModeController implements Dumpable { private int mMode = NAV_BAR_MODE_3BUTTON; private ArrayList<ModeChangedListener> mListeners = new ArrayList<>(); - private String mLastDefaultLauncher; - private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -112,18 +99,6 @@ public class NavigationModeController implements Dumpable { } updateCurrentInteractionMode(true /* notify */); break; - case ACTION_PREFERRED_ACTIVITY_CHANGED: - if (DEBUG) { - Log.d(TAG, "ACTION_PREFERRED_ACTIVITY_CHANGED"); - } - final String launcher = getDefaultLauncherPackageName(mCurrentUserContext); - // Check if it is a default launcher change - if (!TextUtils.equals(mLastDefaultLauncher, launcher)) { - switchFromGestureNavModeIfNotSupportedByDefaultLauncher(); - showNotificationIfDefaultLauncherSupportsGestureNav(); - mLastDefaultLauncher = launcher; - } - break; } } }; @@ -159,7 +134,6 @@ public class NavigationModeController implements Dumpable { // Update the nav mode for the current user updateCurrentInteractionMode(true /* notify */); - switchFromGestureNavModeIfNotSupportedByDefaultLauncher(); // When switching users, defer enabling the gestural nav overlay until the user // is all set up @@ -190,11 +164,7 @@ public class NavigationModeController implements Dumpable { mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null, null); - // We are only interested in launcher changes, so keeping track of the current default. - mLastDefaultLauncher = getDefaultLauncherPackageName(mContext); - updateCurrentInteractionMode(false /* notify */); - switchFromGestureNavModeIfNotSupportedByDefaultLauncher(); // Check if we need to defer enabling gestural nav deferGesturalNavOverlayIfNecessary(); @@ -216,21 +186,13 @@ public class NavigationModeController implements Dumpable { // Already in gesture mode return true; } - final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext); - if (supported == null || supported) { - Log.d(TAG, "Switching system navigation to full-gesture mode:" - + " defaultLauncher=" - + getDefaultLauncherPackageName(mCurrentUserContext) - + " contextUser=" - + mCurrentUserContext.getUserId()); - - setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT); - return true; - } else { - Log.e(TAG, "Gesture nav is not supported for defaultLauncher=" - + getDefaultLauncherPackageName(mCurrentUserContext)); - return false; - } + + Log.d(TAG, "Switching system navigation to full-gesture mode:" + + " contextUser=" + + mCurrentUserContext.getUserId()); + + setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT); + return true; } private boolean enableGestureNav(Intent intent) { @@ -430,100 +392,6 @@ public class NavigationModeController implements Dumpable { }); } - private void switchFromGestureNavModeIfNotSupportedByDefaultLauncher() { - if (getCurrentInteractionMode(mCurrentUserContext) != NAV_BAR_MODE_GESTURAL) { - return; - } - final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext); - if (supported == null || supported) { - return; - } - - Log.d(TAG, "Switching system navigation to 3-button mode:" - + " defaultLauncher=" + getDefaultLauncherPackageName(mCurrentUserContext) - + " contextUser=" + mCurrentUserContext.getUserId()); - - setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT); - showNotification(mCurrentUserContext, R.string.notification_content_system_nav_changed); - mCurrentUserContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) - .edit().putBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, true).apply(); - } - - private void showNotificationIfDefaultLauncherSupportsGestureNav() { - boolean previouslySwitchedFromGestureNav = mCurrentUserContext - .getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) - .getBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false); - if (!previouslySwitchedFromGestureNav) { - return; - } - if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL) { - return; - } - final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext); - if (supported == null || !supported) { - return; - } - - showNotification(mCurrentUserContext, R.string.notification_content_gesture_nav_available); - mCurrentUserContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) - .edit().putBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false).apply(); - } - - /** - * Returns null if there is no default launcher set for the current user. Returns true if the - * current default launcher supports Gesture Navigation. Returns false otherwise. - */ - private Boolean isGestureNavSupportedByDefaultLauncher(Context context) { - final String defaultLauncherPackageName = getDefaultLauncherPackageName(context); - if (DEBUG) { - Log.d(TAG, "isGestureNavSupportedByDefaultLauncher:" - + " defaultLauncher=" + defaultLauncherPackageName - + " contextUser=" + context.getUserId()); - } - if (defaultLauncherPackageName == null) { - return null; - } - if (isSystemApp(context, defaultLauncherPackageName)) { - return true; - } - return false; - } - - private String getDefaultLauncherPackageName(Context context) { - final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>()); - if (cn == null) { - return null; - } - return cn.getPackageName(); - } - - /** Returns true if the app for the given package name is a system app for this device */ - private boolean isSystemApp(Context context, String packageName) { - try { - ApplicationInfo ai = context.getPackageManager().getApplicationInfo(packageName, - PackageManager.GET_META_DATA); - return ai != null && ((ai.flags & SYSTEM_APP_MASK) != 0); - } catch (PackageManager.NameNotFoundException e) { - return false; - } - } - - private void showNotification(Context context, int resId) { - final CharSequence message = context.getResources().getString(resId); - if (DEBUG) { - Log.d(TAG, "showNotification: message=" + message); - } - - final Notification.Builder builder = - new Notification.Builder(mContext, NotificationChannels.ALERTS) - .setContentText(message) - .setStyle(new Notification.BigTextStyle()) - .setSmallIcon(R.drawable.ic_info) - .setAutoCancel(true) - .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0)); - context.getSystemService(NotificationManager.class).notify(TAG, 0, builder.build()); - } - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("NavigationModeController:"); @@ -536,12 +404,6 @@ public class NavigationModeController implements Dumpable { } pw.println(" defaultOverlays=" + defaultOverlays); dumpAssetPaths(mCurrentUserContext); - - pw.println(" defaultLauncher=" + mLastDefaultLauncher); - boolean previouslySwitchedFromGestureNav = mCurrentUserContext - .getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) - .getBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false); - pw.println(" previouslySwitchedFromGestureNav=" + previouslySwitchedFromGestureNav); } private void dumpAssetPaths(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java index d2159ca15b24..ba3406999388 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java @@ -4,7 +4,6 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; -import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -32,7 +31,6 @@ import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.tuner.TunerService; import java.util.ArrayList; import java.util.Objects; @@ -58,7 +56,6 @@ public class NotificationIconAreaController implements DarkReceiver, private final KeyguardBypassController mBypassController; private final DozeParameters mDozeParameters; - private boolean mShowSilentOnLockscreen = true; private int mIconSize; private int mIconHPadding; private int mIconTint = Color.WHITE; @@ -81,6 +78,7 @@ public class NotificationIconAreaController implements DarkReceiver, private int mAodIconTint; private boolean mFullyHidden; private boolean mAodIconsVisible; + private boolean mIsPulsing; public NotificationIconAreaController(Context context, StatusBar statusBar, StatusBarStateController statusBarStateController, @@ -101,11 +99,6 @@ public class NotificationIconAreaController implements DarkReceiver, initializeNotificationAreaViews(context); reloadAodColor(); - - TunerService tunerService = Dependency.get(TunerService.class); - tunerService.addTunable((key, newValue) -> { - mShowSilentOnLockscreen = "1".equals(newValue); - }, Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS); } protected View inflateIconArea(LayoutInflater inflater) { @@ -238,7 +231,7 @@ public class NotificationIconAreaController implements DarkReceiver, } protected boolean shouldShowNotificationIcon(NotificationEntry entry, - boolean showAmbient, boolean showLowPriority, boolean hideDismissed, + boolean showAmbient, boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon, boolean hidePulsing, boolean onlyShowCenteredIcon) { @@ -257,9 +250,6 @@ public class NotificationIconAreaController implements DarkReceiver, if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) { return false; } - if (!showLowPriority && !entry.isHighPriority()) { - return false; - } if (!entry.isTopLevelChild()) { return false; } @@ -276,7 +266,9 @@ public class NotificationIconAreaController implements DarkReceiver, if (!showAmbient && entry.shouldSuppressStatusBar()) { return false; } - if (hidePulsing && entry.showingPulsing()) { + if (hidePulsing && entry.showingPulsing() + && (!mWakeUpCoordinator.getNotificationsFullyHidden() + || !entry.isPulseSuppressed())) { return false; } return true; @@ -297,7 +289,6 @@ public class NotificationIconAreaController implements DarkReceiver, private void updateShelfIcons() { updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons, true /* showAmbient */, - true /* showLowPriority */, false /* hideDismissed */, false /* hideRepliedMessages */, false /* hideCurrentMedia */, @@ -309,7 +300,6 @@ public class NotificationIconAreaController implements DarkReceiver, public void updateStatusBarIcons() { updateIconsForLayout(entry -> entry.icon, mNotificationIcons, false /* showAmbient */, - true /* showLowPriority */, true /* hideDismissed */, true /* hideRepliedMessages */, false /* hideCurrentMedia */, @@ -321,7 +311,6 @@ public class NotificationIconAreaController implements DarkReceiver, private void updateCenterIcon() { updateIconsForLayout(entry -> entry.centeredIcon, mCenteredIcon, false /* showAmbient */, - true /* showLowPriority */, false /* hideDismissed */, false /* hideRepliedMessages */, false /* hideCurrentMedia */, @@ -333,7 +322,6 @@ public class NotificationIconAreaController implements DarkReceiver, public void updateAodNotificationIcons() { updateIconsForLayout(entry -> entry.aodIcon, mAodIcons, false /* showAmbient */, - mShowSilentOnLockscreen /* showLowPriority */, true /* hideDismissed */, true /* hideRepliedMessages */, true /* hideCurrentMedia */, @@ -353,7 +341,7 @@ public class NotificationIconAreaController implements DarkReceiver, * @param hidePulsing should pulsing notifications be hidden */ private void updateIconsForLayout(Function<NotificationEntry, StatusBarIconView> function, - NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority, + NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon, boolean hidePulsing, boolean onlyShowCenteredIcon) { ArrayList<StatusBarIconView> toShow = new ArrayList<>( @@ -364,7 +352,7 @@ public class NotificationIconAreaController implements DarkReceiver, View view = mNotificationScrollLayout.getChildAt(i); if (view instanceof ExpandableNotificationRow) { NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry(); - if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed, + if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed, hideRepliedMessages, hideCurrentMedia, hideCenteredIcon, hidePulsing, onlyShowCenteredIcon)) { StatusBarIconView iconView = function.apply(ent); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 971a7eeaca12..792b83a2827c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -454,6 +454,11 @@ public class NotificationPanelView extends PanelView implements mPulseExpansionHandler.setUp(mNotificationStackScroller, this, mShadeController); mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() { @Override + public void onFullyHiddenChanged(boolean isFullyHidden) { + updateKeyguardStatusBarForHeadsUp(); + } + + @Override public void onPulseExpansionChanged(boolean expandingChanged) { if (mKeyguardBypassController.getBypassEnabled()) { // Position the notifications while dragging down while pulsing @@ -803,8 +808,7 @@ public class NotificationPanelView extends PanelView implements if (suppressedSummary) { continue; } - if (!mLockscreenUserManager.shouldShowOnKeyguard( - row.getStatusBarNotification())) { + if (!mLockscreenUserManager.shouldShowOnKeyguard(row.getEntry())) { continue; } if (row.isRemoved()) { @@ -1278,6 +1282,7 @@ public class NotificationPanelView extends PanelView implements } mExpectingSynthesizedDown = true; onTrackingStarted(); + updatePanelExpanded(); } /** @@ -1560,9 +1565,15 @@ public class NotificationPanelView extends PanelView implements anim.setStartDelay(mKeyguardMonitor.isKeyguardFadingAway() ? mKeyguardMonitor.getKeyguardFadingAwayDelay() : 0); - anim.setDuration(mKeyguardMonitor.isKeyguardFadingAway() - ? mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2 - : StackStateAnimator.ANIMATION_DURATION_STANDARD); + + long duration; + if (mKeyguardMonitor.isKeyguardFadingAway()) { + duration = mKeyguardMonitor.getShortenedFadingAwayDuration(); + } else { + duration = StackStateAnimator.ANIMATION_DURATION_STANDARD; + } + anim.setDuration(duration); + anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); anim.addListener(new AnimatorListenerAdapter() { @Override @@ -1605,7 +1616,7 @@ public class NotificationPanelView extends PanelView implements mKeyguardBottomArea.animate() .alpha(0f) .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay()) - .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2) + .setDuration(mKeyguardMonitor.getShortenedFadingAwayDuration()) .setInterpolator(Interpolators.ALPHA_OUT) .withEndAction(mAnimateKeyguardBottomAreaInvisibleEndRunnable) .start(); @@ -1634,7 +1645,7 @@ public class NotificationPanelView extends PanelView implements if (keyguardFadingAway) { mKeyguardStatusView.animate() .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay()) - .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2) + .setDuration(mKeyguardMonitor.getShortenedFadingAwayDuration()) .start(); } } else if (mBarState == StatusBarState.SHADE_LOCKED @@ -1717,8 +1728,8 @@ public class NotificationPanelView extends PanelView implements mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */, false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */); } - if (mExpansionListener != null) { - mExpansionListener.onQsExpansionChanged(mQsMaxExpansionHeight != 0 + for (int i = 0; i < mExpansionListeners.size(); i++) { + mExpansionListeners.get(i).onQsExpansionChanged(mQsMaxExpansionHeight != 0 ? mQsExpansionHeight / mQsMaxExpansionHeight : 0); } if (DEBUG) { @@ -2029,7 +2040,7 @@ public class NotificationPanelView extends PanelView implements } private void updatePanelExpanded() { - boolean isExpanded = !isFullyCollapsed(); + boolean isExpanded = !isFullyCollapsed() || mExpectingSynthesizedDown; if (mPanelExpanded != isExpanded) { mHeadsUpManager.setIsPanelExpanded(isExpanded); mStatusBar.setPanelExpanded(isExpanded); @@ -3374,24 +3385,4 @@ public class NotificationPanelView extends PanelView implements mOnReinflationListener = onReinflationListener; } - /** - * Panel and QS expansion callbacks. - */ - public interface PanelExpansionListener { - /** - * Invoked whenever the notification panel expansion changes, at every animation frame. - * This is the main expansion that happens when the user is swiping up to dismiss the - * lock screen. - * - * @param expansion 0 when collapsed, 1 when expanded. - * @param tracking {@code true} when the user is actively dragging the panel. - */ - void onPanelExpansionChanged(float expansion, boolean tracking); - - /** - * Invoked whenever the QS expansion changes, at every animation frame. - * @param expansion 0 when collapsed, 1 when expanded. - */ - void onQsExpansionChanged(float expansion); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelExpansionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelExpansionListener.java new file mode 100644 index 000000000000..655a25d22337 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelExpansionListener.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar.phone; + +/** + * Panel and QS expansion callbacks. + */ +public interface PanelExpansionListener { + /** + * Invoked whenever the notification panel expansion changes, at every animation frame. + * This is the main expansion that happens when the user is swiping up to dismiss the + * lock screen. + * + * @param expansion 0 when collapsed, 1 when expanded. + * @param tracking {@code true} when the user is actively dragging the panel. + */ + void onPanelExpansionChanged(float expansion, boolean tracking); + + /** + * Invoked whenever the QS expansion changes, at every animation frame. + * @param expansion 0 when collapsed, 1 when expanded. + */ + default void onQsExpansionChanged(float expansion) {}; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 853faabbbc81..727f72b36ed8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -49,11 +49,11 @@ import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; -import com.android.systemui.statusbar.phone.NotificationPanelView.PanelExpansionListener; import com.android.systemui.statusbar.policy.KeyguardMonitor; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; public abstract class PanelView extends FrameLayout { public static final boolean DEBUG = PanelBar.DEBUG; @@ -68,7 +68,7 @@ public abstract class PanelView extends FrameLayout { private boolean mVibrateOnOpening; protected boolean mLaunchingNotification; private int mFixedDuration = NO_FIXED_DURATION; - protected PanelExpansionListener mExpansionListener; + protected ArrayList<PanelExpansionListener> mExpansionListeners = new ArrayList<>(); private final void logf(String fmt, Object... args) { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); @@ -1173,13 +1173,13 @@ public abstract class PanelView extends FrameLayout { || mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp() || mTracking || mHeightAnimator != null); } - if (mExpansionListener != null) { - mExpansionListener.onPanelExpansionChanged(mExpandedFraction, mTracking); + for (int i = 0; i < mExpansionListeners.size(); i++) { + mExpansionListeners.get(i).onPanelExpansionChanged(mExpandedFraction, mTracking); } } - public void setExpansionListener(PanelExpansionListener panelExpansionListener) { - mExpansionListener = panelExpansionListener; + public void addExpansionListener(PanelExpansionListener panelExpansionListener) { + mExpansionListeners.add(panelExpansionListener); } protected abstract boolean isPanelVisibleBecauseOfHeadsUp(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 660810fe7eb9..8efd952e67c5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -46,7 +46,6 @@ import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.policy.HeadsUpManager; import java.util.Objects; @@ -279,7 +278,7 @@ public class PhoneStatusBarView extends PanelBar { super.panelExpansionChanged(frac, expanded); updateScrimFraction(); if ((frac == 0 || frac == 1) && mBar.getNavigationBarView() != null) { - mBar.getNavigationBarView().onPanelExpandedChange(); + mBar.getNavigationBarView().onStatusBarPanelStateChanged(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 1aec5e4d0b1d..b12bf5c39970 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -491,8 +491,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo * away once the display turns on. */ public void prepareForGentleWakeUp() { - if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) { + if (mState == ScrimState.AOD) { mCurrentInFrontAlpha = 1f; + mCurrentInFrontTint = Color.BLACK; + mCurrentBehindTint = Color.BLACK; mAnimateChange = false; updateScrims(); mAnimateChange = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 763e0d70469b..c706062d3bb3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -129,7 +129,10 @@ public enum ScrimState { public void prepare(ScrimState previousState) { mCurrentInFrontAlpha = 0f; mCurrentBehindTint = Color.BLACK; + mCurrentInFrontTint = Color.BLACK; mBlankScreen = mDisplayRequiresBlanking; + mAnimationDuration = mWakeLockScreenSensorActive + ? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index f8e6aa3b844f..f15b60123a80 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -489,9 +489,12 @@ public class StatusBar extends SystemUI implements DemoMode, WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT); final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean( com.android.internal.R.bool.config_dozeSupportsAodWallpaper); + final boolean imageWallpaperInAmbient = + !DozeParameters.getInstance(mContext).getDisplayNeedsBlanking(); // If WallpaperInfo is null, it must be ImageWallpaper. final boolean supportsAmbientMode = deviceSupportsAodWallpaper - && (info == null || info.supportsAmbientMode()); + && ((info == null && imageWallpaperInAmbient) + || (info != null && info.supportsAmbientMode())); mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode); mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); @@ -813,6 +816,7 @@ public class StatusBar extends SystemUI implements DemoMode, inflateShelf(); mNotificationIconAreaController.setupShelf(mNotificationShelf); mNotificationPanel.setOnReinflationListener(mNotificationIconAreaController::initAodIcons); + mNotificationPanel.addExpansionListener(mWakeUpCoordinator); Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController); // Allow plugins to reference DarkIconDispatcher and StatusBarStateController @@ -855,7 +859,8 @@ public class StatusBar extends SystemUI implements DemoMode, } mHeadsUpAppearanceController = new HeadsUpAppearanceController( mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow, - mStatusBarStateController, mKeyguardBypassController); + mStatusBarStateController, mKeyguardBypassController, + mWakeUpCoordinator); mHeadsUpAppearanceController.readFrom(oldController); mStatusBarWindow.setStatusBarView(mStatusBarView); updateAreThereNotifications(); @@ -1507,6 +1512,9 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationPanel.setStatusAccessibilityImportance(expanded ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + if (getNavigationBarView() != null) { + getNavigationBarView().onStatusBarPanelStateChanged(); + } } public boolean isWakeUpComingFromTouch() { @@ -1577,7 +1585,8 @@ public class StatusBar extends SystemUI implements DemoMode, public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) { mEntryManager.updateNotifications(); if (isDozing() && isHeadsUp) { - mDozeServiceHost.fireNotificationPulse(); + entry.setPulseSuppressed(false); + mDozeServiceHost.fireNotificationPulse(entry); if (mPulsing) { mDozeScrimController.cancelPendingPulseTimeout(); } @@ -1801,6 +1810,8 @@ public class StatusBar extends SystemUI implements DemoMode, mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK); } mNotificationPanel.expand(true /* animate */); + ((NotificationListContainer) mStackScroller).setWillExpand(true); + mHeadsUpManager.unpinAll(true /* userUnpinned */); mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1); } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){ mNotificationPanel.flingSettings(0 /* velocity */, @@ -1938,7 +1949,6 @@ public class StatusBar extends SystemUI implements DemoMode, if (start) { mNotificationPanel.startWaitingForOpenPanelGesture(); - setPanelExpanded(true); } else { mNotificationPanel.stopWaitingForOpenPanelGesture(velocity); } @@ -2387,6 +2397,10 @@ public class StatusBar extends SystemUI implements DemoMode, mLightBarController.dump(fd, pw, args); } + if (mUnlockMethodCache != null) { + mUnlockMethodCache.dump(pw); + } + if (mKeyguardBypassController != null) { mKeyguardBypassController.dump(pw); } @@ -3199,12 +3213,13 @@ public class StatusBar extends SystemUI implements DemoMode, /** * Notifies the status bar the Keyguard is fading away with the specified timings. - * - * @param startTime the start time of the animations in uptime millis + * @param startTime the start time of the animations in uptime millis * @param delay the precalculated animation delay in milliseconds * @param fadeoutDuration the duration of the exit animation, in milliseconds + * @param isBypassFading is this a fading away animation while bypassing */ - public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) { + public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration, + boolean isBypassFading) { mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); @@ -3212,7 +3227,7 @@ public class StatusBar extends SystemUI implements DemoMode, mCommandQueue.appTransitionStarting(mDisplayId, startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); - mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration); + mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading); } /** @@ -3562,6 +3577,9 @@ public class StatusBar extends SystemUI implements DemoMode, userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId()) || !mLockscreenUserManager.shouldShowLockscreenNotifications() || mFalsingManager.shouldEnforceBouncer(); + if (mKeyguardBypassController.getBypassEnabled()) { + fullShadeNeedsBouncer = false; + } if (mLockscreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) { mStatusBarStateController.setLeaveOpenOnKeyguardHide(true); showBouncerIfKeyguard(); @@ -3919,9 +3937,13 @@ public class StatusBar extends SystemUI implements DemoMode, } } - public void fireNotificationPulse() { + public void fireNotificationPulse(NotificationEntry entry) { + Runnable pulseSupressedListener = () -> { + entry.setPulseSuppressed(true); + mNotificationIconAreaController.updateAodNotificationIcons(); + }; for (Callback callback : mCallbacks) { - callback.onNotificationAlerted(); + callback.onNotificationAlerted(pulseSupressedListener); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 5ce1329d5a89..3508c90bc8a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -70,7 +70,7 @@ import java.util.ArrayList; */ public class StatusBarKeyguardViewManager implements RemoteInputController.Callback, StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener, - NotificationPanelView.PanelExpansionListener, NavigationModeController.ModeChangedListener { + PanelExpansionListener, NavigationModeController.ModeChangedListener { // When hiding the Keyguard with timing supplied from WindowManager, better be early than late. private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3; @@ -223,7 +223,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry, mExpansionCallback, falsingManager); mNotificationPanelView = notificationPanelView; - notificationPanelView.setExpansionListener(this); + notificationPanelView.addExpansionListener(this); mBypassController = bypassController; mNotificationContainer = notificationContainer; } @@ -561,18 +561,22 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb executeAfterKeyguardGoneAction(); boolean wakeUnlockPulsing = mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; - if (wakeUnlockPulsing) { + boolean needsFading = needsBypassFading(); + if (needsFading) { + delay = 0; + fadeoutDuration = KeyguardBypassController.BYPASS_PANEL_FADE_DURATION; + } else if (wakeUnlockPulsing) { delay = 0; fadeoutDuration = 240; } - mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration); + mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration, needsFading); mBiometricUnlockController.startKeyguardFadingAway(); hideBouncer(true /* destroyView */); if (wakeUnlockPulsing) { - if (needsBypassFading()) { + if (needsFading) { ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView, mNotificationContainer, - KeyguardBypassController.BYPASS_PANEL_FADE_DURATION, + fadeoutDuration, () -> { mStatusBar.hideKeyguard(); onKeyguardFadedAway(); @@ -585,10 +589,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); if (!staying) { mStatusBarWindowController.setKeyguardFadingAway(true); - if (needsBypassFading()) { + if (needsFading) { ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView, mNotificationContainer, - KeyguardBypassController.BYPASS_PANEL_FADE_DURATION, + fadeoutDuration, () -> { mStatusBar.hideKeyguard(); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java index 4ddd0e9962ad..d9a9f7cbc2a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -51,12 +51,13 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; import com.google.android.collect.Lists; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.lang.reflect.Field; - import java.util.ArrayList; + import javax.inject.Inject; import javax.inject.Singleton; @@ -352,7 +353,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat } private void applyForceStatusBarVisibleFlag(State state) { - if (state.forceStatusBarVisible) { + if (state.forceStatusBarVisible || state.forcePluginOpen) { mLpChanged.privateFlags |= WindowManager .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index f1049f005dea..33b863fd0236 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -418,7 +418,7 @@ public class StatusBarWindowView extends FrameLayout { if (mNotificationPanel.isFullyExpanded() && mStatusBarStateController.getState() == StatusBarState.KEYGUARD && !mService.isBouncerShowing() - && !mBypassController.getBypassEnabled() + && (!mBypassController.getBypassEnabled() || mNotificationPanel.isQsExpanded()) && !mService.isDozing()) { intercept = mDragDownHelper.onInterceptTouchEvent(ev); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java index a71fcdbd9914..b1d6ca6e5580 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java @@ -28,6 +28,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import java.io.PrintWriter; import java.util.ArrayList; /** @@ -51,7 +52,7 @@ public class UnlockMethodCache { private boolean mTrustManaged; private boolean mTrusted; private boolean mDebugUnlocked = false; - private boolean mIsUnlockingWithFacePossible; + private boolean mFaceAuthEnabled; private UnlockMethodCache(Context ctx) { mLockPatternUtils = new LockPatternUtils(ctx); @@ -110,8 +111,8 @@ public class UnlockMethodCache { /** * If there are faces enrolled and user enabled face auth on keyguard. */ - public boolean isUnlockingWithFacePossible() { - return mIsUnlockingWithFacePossible; + public boolean isFaceAuthEnabled() { + return mFaceAuthEnabled; } private void update(boolean updateAlways) { @@ -122,16 +123,16 @@ public class UnlockMethodCache { || (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked); boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user); boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user); - boolean isUnlockingWithFacePossible = mKeyguardUpdateMonitor.isUnlockWithFacePossible(user); + boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user); boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer || trustManaged != mTrustManaged - || mIsUnlockingWithFacePossible != isUnlockingWithFacePossible; + || mFaceAuthEnabled != faceAuthEnabled; if (changed || updateAlways) { mSecure = secure; mCanSkipBouncer = canSkipBouncer; mTrusted = trusted; mTrustManaged = trustManaged; - mIsUnlockingWithFacePossible = isUnlockingWithFacePossible; + mFaceAuthEnabled = faceAuthEnabled; notifyListeners(); } Trace.endSection(); @@ -143,6 +144,16 @@ public class UnlockMethodCache { } } + public void dump(PrintWriter pw) { + pw.println("UnlockMethodCache"); + pw.println(" mSecure: " + mSecure); + pw.println(" mCanSkipBouncer: " + mCanSkipBouncer); + pw.println(" mTrustManaged: " + mTrustManaged); + pw.println(" mTrusted: " + mTrusted); + pw.println(" mDebugUnlocked: " + mDebugUnlocked); + pw.println(" mFaceAuthEnabled: " + mFaceAuthEnabled); + } + private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() { @Override public void onUserSwitchComplete(int userId) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java index f61b556e22ab..070136ec94c1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java @@ -29,6 +29,19 @@ public interface KeyguardMonitor extends CallbackController<Callback> { long getKeyguardFadingAwayDelay(); long calculateGoingToFullShadeDelay(); + /** + * @return a shortened fading away duration similar to + * {{@link #getKeyguardFadingAwayDuration()}} which may only span half of the duration, unless + * we're bypassing + */ + default long getShortenedFadingAwayDuration() { + if (isBypassFadingAnimation()) { + return getKeyguardFadingAwayDuration(); + } else { + return getKeyguardFadingAwayDuration() / 2; + } + } + default boolean isDeviceInteractive() { return false; } @@ -39,7 +52,21 @@ public interface KeyguardMonitor extends CallbackController<Callback> { default void notifyKeyguardGoingAway(boolean b) { } - default void notifyKeyguardFadingAway(long delay, long fadeoutDuration) { + /** + * @return {@code true} if the current fading away animation is the fast bypass fading. + */ + default boolean isBypassFadingAnimation() { + return false; + } + + /** + * Notifies that the Keyguard is fading away with the specified timings. + * @param delay the precalculated animation delay in milliseconds + * @param fadeoutDuration the duration of the exit animation, in milliseconds + * @param isBypassFading is this a fading away animation while bypassing + */ + default void notifyKeyguardFadingAway(long delay, long fadeoutDuration, + boolean isBypassFading) { } default void notifyKeyguardDoneFading() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java index 68d00708b0d3..8829be4ee0f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java @@ -54,6 +54,7 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback private long mKeyguardFadingAwayDuration; private boolean mKeyguardGoingAway; private boolean mLaunchTransitionFadingAway; + private boolean mBypassFadingAnimation; /** */ @@ -140,10 +141,11 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged); } - public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) { + public void notifyKeyguardFadingAway(long delay, long fadeoutDuration, boolean isBypassFading) { setKeyguardFadingAway(true); mKeyguardFadingAwayDelay = delay; mKeyguardFadingAwayDuration = fadeoutDuration; + mBypassFadingAnimation = isBypassFading; } private void setKeyguardFadingAway(boolean keyguardFadingAway) { @@ -172,6 +174,11 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback } @Override + public boolean isBypassFadingAnimation() { + return mBypassFadingAnimation; + } + + @Override public long getKeyguardFadingAwayDelay() { return mKeyguardFadingAwayDelay; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index eb8ef09d0635..d4642238d8fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -95,13 +95,13 @@ public class DozeTriggersTest extends SysuiTestCase { mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE); clearInvocations(mMachine); - mHost.callback.onNotificationAlerted(); + mHost.callback.onNotificationAlerted(null /* pulseSuppressedListener */); mSensors.getMockProximitySensor().sendProximityResult(false); /* Near */ verify(mMachine, never()).requestState(any()); verify(mMachine, never()).requestPulse(anyInt()); - mHost.callback.onNotificationAlerted(); + mHost.callback.onNotificationAlerted(null /* pulseSuppressedListener */); mSensors.getMockProximitySensor().sendProximityResult(true); /* Far */ verify(mMachine).requestPulse(anyInt()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java index 893f3d184acb..9576cb2eec45 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java @@ -48,6 +48,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.ZenModeController; @@ -197,6 +198,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { @Test public void onMetadataChanged_updatesSlice() { + mProvider.onStateChanged(StatusBarState.KEYGUARD); mProvider.onDozingChanged(true); reset(mContentResolver); mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING); @@ -210,6 +212,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { @Test public void onDozingChanged_updatesSliceIfMedia() { + mProvider.onStateChanged(StatusBarState.KEYGUARD); mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING); reset(mContentResolver); // Show media when dozing diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java new file mode 100644 index 000000000000..eb71dd6ee677 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.recents.model; + + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNull; + +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@SmallTest +@RunWith(JUnit4.class) +public class TaskKeyLruCacheTest extends SysuiTestCase { + private static int sCacheSize = 3; + private static int sIdTask1 = 1; + private static int sIdTask2 = 2; + private static int sIdTask3 = 3; + private static int sIdUser1 = 1; + + TaskKeyCache<Integer> mCache = new TaskKeyLruCache<>(sCacheSize, null); + Task.TaskKey mKey1; + Task.TaskKey mKey2; + Task.TaskKey mKey3; + + @Before + public void setup() { + mKey1 = new Task.TaskKey(sIdTask1, 0, null, null, sIdUser1, System.currentTimeMillis()); + mKey2 = new Task.TaskKey(sIdTask2, 0, null, null, sIdUser1, System.currentTimeMillis()); + mKey3 = new Task.TaskKey(sIdTask3, 0, null, null, sIdUser1, System.currentTimeMillis()); + } + + @Test + public void addSingleItem_get_success() { + mCache.put(mKey1, 1); + + assertEquals(1, (int) mCache.get(mKey1)); + } + + @Test + public void addSingleItem_getUninsertedItem_returnsNull() { + mCache.put(mKey1, 1); + + assertNull(mCache.get(mKey2)); + } + + @Test + public void emptyCache_get_returnsNull() { + assertNull(mCache.get(mKey1)); + } + + @Test + public void updateItem_get_returnsSecond() { + mCache.put(mKey1, 1); + mCache.put(mKey1, 2); + + assertEquals(2, (int) mCache.get(mKey1)); + assertEquals(1, mCache.mKeys.size()); + } + + @Test + public void fillCache_put_evictsOldest() { + mCache.put(mKey1, 1); + mCache.put(mKey2, 2); + mCache.put(mKey3, 3); + Task.TaskKey key4 = new Task.TaskKey(sIdTask3 + 1, 0, + null, null, sIdUser1, System.currentTimeMillis()); + mCache.put(key4, 4); + + assertNull(mCache.get(mKey1)); + assertEquals(3, mCache.mKeys.size()); + assertEquals(mKey2, mCache.mKeys.valueAt(0)); + } + + @Test + public void fillCache_remove_success() { + mCache.put(mKey1, 1); + mCache.put(mKey2, 2); + mCache.put(mKey3, 3); + + mCache.remove(mKey2); + + assertNull(mCache.get(mKey2)); + assertEquals(2, mCache.mKeys.size()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java index 49a263a8d781..57dd8c94c790 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java @@ -38,7 +38,6 @@ import android.os.Handler; import android.os.Looper; import android.os.UserManager; import android.provider.Settings; -import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -48,6 +47,7 @@ import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationData; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.DeviceProvisionedController; @@ -166,7 +166,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1); when(mNotificationData.isHighPriority(any())).thenReturn(false); - assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(mock(StatusBarNotification.class))); + assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(mock(NotificationEntry.class))); } @Test @@ -179,7 +179,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0); when(mNotificationData.isHighPriority(any())).thenReturn(false); - assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(mock(StatusBarNotification.class))); + assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(mock(NotificationEntry.class))); } private class TestNotificationLockscreenUserManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java index 73abda9a5da7..59d0f912d38e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java @@ -263,6 +263,8 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { when(notifRow.getVisibility()).thenReturn(View.VISIBLE); when(notifRow.getEntry().isHighPriority()) .thenReturn(children[i] == ChildType.HIPRI); + when(notifRow.getEntry().isTopBucket()) + .thenReturn(children[i] == ChildType.HIPRI); when(notifRow.getParent()).thenReturn(mNssl); child = notifRow; break; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 7d9920db36a4..fd676111b1da 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -82,7 +82,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true); when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true); - when(mUnlockMethodCache.isUnlockingWithFacePossible()).thenReturn(true); + when(mUnlockMethodCache.isFaceAuthEnabled()).thenReturn(true); when(mKeyguardBypassController.onBiometricAuthenticated(any())).thenReturn(true); when(mKeyguardBypassController.canPlaySubtleWindowAnimations()).thenReturn(true); mContext.addMockSystemService(PowerManager.class, mPowerManager); @@ -161,6 +161,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { @Test public void onBiometricAuthenticated_whenFace_andBypass_encrypted_showBouncer() { + reset(mUpdateMonitor); when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true); mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); @@ -168,11 +169,18 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, BiometricSourceType.FACE); + // Wake up before showing the bouncer + verify(mStatusBarKeyguardViewManager, never()).showBouncer(eq(false)); + mBiometricUnlockController.mWakefulnessObserver.onFinishedWakingUp(); + verify(mStatusBarKeyguardViewManager).showBouncer(eq(false)); + assertThat(mBiometricUnlockController.getMode()) + .isEqualTo(BiometricUnlockController.MODE_SHOW_BOUNCER); } @Test public void onBiometricAuthenticated_whenFace_noBypass_encrypted_doNothing() { + reset(mUpdateMonitor); mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(false); @@ -181,6 +189,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean()); verify(mStatusBarKeyguardViewManager, never()).animateCollapsePanels(anyFloat()); + assertThat(mBiometricUnlockController.getMode()) + .isEqualTo(BiometricUnlockController.MODE_NONE); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java index b45707ef6c10..a38094da3e1c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java @@ -35,6 +35,7 @@ import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.HeadsUpStatusBarView; import com.android.systemui.statusbar.NotificationTestHelper; +import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; @@ -59,6 +60,7 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { private View mOperatorNameView; private StatusBarStateController mStatusbarStateController; private KeyguardBypassController mBypassController; + private NotificationWakeUpCoordinator mWakeUpCoordinator; @Before public void setUp() throws Exception { @@ -72,11 +74,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { mOperatorNameView = new View(mContext); mStatusbarStateController = mock(StatusBarStateController.class); mBypassController = mock(KeyguardBypassController.class); + mWakeUpCoordinator = mock(NotificationWakeUpCoordinator.class); mHeadsUpAppearanceController = new HeadsUpAppearanceController( mock(NotificationIconAreaController.class), mHeadsUpManager, mStatusbarStateController, mBypassController, + mWakeUpCoordinator, mHeadsUpStatusBarView, mStackScroller, mPanelView, @@ -153,6 +157,7 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { mHeadsUpManager, mStatusbarStateController, mBypassController, + mWakeUpCoordinator, mHeadsUpStatusBarView, mStackScroller, mPanelView, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java index 4e0ef56ad830..907e695f2513 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java @@ -379,7 +379,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { @Test public void testShow_delaysIfFaceAuthIsRunning() { - when(mUnlockMethodCache.isUnlockingWithFacePossible()).thenReturn(true); + when(mUnlockMethodCache.isFaceAuthEnabled()).thenReturn(true); mBouncer.show(true /* reset */); ArgumentCaptor<Runnable> showRunnable = ArgumentCaptor.forClass(Runnable.class); @@ -394,4 +394,15 @@ public class KeyguardBouncerTest extends SysuiTestCase { public void testRegisterUpdateMonitorCallback() { verify(mKeyguardUpdateMonitor).registerCallback(any()); } + + @Test + public void testInTransit_whenTranslation() { + mBouncer.show(true); + mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); + assertThat(mBouncer.inTransit()).isFalse(); + mBouncer.setExpansion(0.5f); + assertThat(mBouncer.inTransit()).isTrue(); + mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); + assertThat(mBouncer.inTransit()).isFalse(); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index d8e90a584058..0dbf30881ffe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -225,11 +225,12 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); - // Front scrim should be transparent + // Front scrim should be transparent, but tinted // Back scrim should be semi-transparent so the user can see the wallpaper // Pulse callback should have been invoked assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); assertScrimTint(mScrimBehind, true /* tinted */); + assertScrimTint(mScrimInFront, true /* tinted */); mScrimController.setWakeLockScreenSensorActive(true); mScrimController.finishAnimationsImmediately(); diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto index f9a2ca269335..8ad24894a1b9 100644 --- a/proto/src/wifi.proto +++ b/proto/src/wifi.proto @@ -551,6 +551,30 @@ message WifiLog { // Histogram of the EAP method type of all installed Passpoint profiles for R2 repeated PasspointProfileTypeCount installed_passpoint_profile_type_for_r2 = 148; + + // Histogram of Tx link speed at 2G + repeated Int32Count tx_link_speed_count_2g = 149; + + // Histogram of Tx link speed at 5G low band + repeated Int32Count tx_link_speed_count_5g_low = 150; + + // Histogram of Tx link speed at 5G middle band + repeated Int32Count tx_link_speed_count_5g_mid = 151; + + // Histogram of Tx link speed at 5G high band + repeated Int32Count tx_link_speed_count_5g_high = 152; + + // Histogram of Rx link speed at 2G + repeated Int32Count rx_link_speed_count_2g = 153; + + // Histogram of Rx link speed at 5G low band + repeated Int32Count rx_link_speed_count_5g_low = 154; + + // Histogram of Rx link speed at 5G middle band + repeated Int32Count rx_link_speed_count_5g_mid = 155; + + // Histogram of Rx link speed at 5G high band + repeated Int32Count rx_link_speed_count_5g_high = 156; } // Information that gets logged for every WiFi connection. @@ -827,6 +851,7 @@ message LinkSpeedCount { optional int64 rssi_sum_of_squares_dbm_sq = 4; } + // Number of occurrences of Soft AP session durations message SoftApDurationBucket { // Bucket covers duration : [duration_sec, duration_sec + bucket_size_sec) diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java index 2db7f0e108b4..d923bedd15c1 100644 --- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java @@ -23,6 +23,7 @@ import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCE import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; +import android.accessibilityservice.AccessibilityGestureInfo; import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; @@ -89,7 +90,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ protected final Context mContext; protected final SystemSupport mSystemSupport; - private final WindowManagerInternal mWindowManagerService; + protected final WindowManagerInternal mWindowManagerService; private final GlobalActionPerformer mGlobalActionPerformer; private final AccessibilityWindowManager mA11yWindowManager; private final DisplayManager mDisplayManager; @@ -167,9 +168,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ @Nullable MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId); /** - * @return The current injector of motion events, if one exists + * @param displayId The display id. + * @return The current injector of motion events used on the display, if one exists. */ - @Nullable MotionEventInjector getMotionEventInjectorLocked(); + @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId); /** * @return The current dispatcher for fingerprint gestures, if one exists @@ -715,6 +717,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } @Override + public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) { + } + + @Override public boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) @@ -1159,9 +1165,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } } - public void notifyGesture(int gestureId) { + public void notifyGesture(AccessibilityGestureInfo gestureInfo) { mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, - gestureId, 0).sendToTarget(); + gestureInfo).sendToTarget(); } public void notifyClearAccessibilityNodeInfoCache() { @@ -1250,13 +1256,13 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ } } - private void notifyGestureInternal(int gestureId) { + private void notifyGestureInternal(AccessibilityGestureInfo gestureInfo) { final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); if (listener != null) { try { - listener.onGesture(gestureId); + listener.onGesture(gestureInfo); } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error during sending gesture " + gestureId + Slog.e(LOG_TAG, "Error during sending gesture " + gestureInfo + " to " + mService, re); } } @@ -1451,8 +1457,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int type = message.what; switch (type) { case MSG_ON_GESTURE: { - final int gestureId = message.arg1; - notifyGestureInternal(gestureId); + notifyGestureInternal((AccessibilityGestureInfo) message.obj); } break; case MSG_CLEAR_ACCESSIBILITY_CACHE: { diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java index d7670112d55c..b4ac92f0cf55 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java @@ -16,21 +16,15 @@ package com.android.server.accessibility; +import android.accessibilityservice.AccessibilityGestureInfo; import android.accessibilityservice.AccessibilityService; import android.content.Context; -import android.gesture.Gesture; import android.gesture.GesturePoint; -import android.gesture.GestureStore; -import android.gesture.GestureStroke; -import android.gesture.Prediction; import android.graphics.PointF; import android.util.Slog; import android.util.TypedValue; import android.view.GestureDetector; import android.view.MotionEvent; -import android.view.ViewConfiguration; - -import com.android.internal.R; import java.util.ArrayList; @@ -125,11 +119,11 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen /** * Called when an event stream is recognized as a gesture. * - * @param gestureId ID of the gesture that was recognized. + * @param gestureInfo Information about the gesture. * * @return true if the event is consumed, else false */ - boolean onGestureCompleted(int gestureId); + boolean onGestureCompleted(AccessibilityGestureInfo gestureInfo); /** * Called when the system has decided an event stream doesn't match any @@ -562,6 +556,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen private boolean recognizeGesturePath(MotionEvent event, int policyFlags, ArrayList<PointF> path) { + final int displayId = event.getDisplayId(); if (path.size() == 2) { PointF start = path.get(0); PointF end = path.get(1); @@ -571,13 +566,21 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen int direction = toDirection(dX, dY); switch (direction) { case LEFT: - return mListener.onGestureCompleted(AccessibilityService.GESTURE_SWIPE_LEFT); + return mListener.onGestureCompleted( + new AccessibilityGestureInfo(AccessibilityService.GESTURE_SWIPE_LEFT, + displayId)); case RIGHT: - return mListener.onGestureCompleted(AccessibilityService.GESTURE_SWIPE_RIGHT); + return mListener.onGestureCompleted( + new AccessibilityGestureInfo(AccessibilityService.GESTURE_SWIPE_RIGHT, + displayId)); case UP: - return mListener.onGestureCompleted(AccessibilityService.GESTURE_SWIPE_UP); + return mListener.onGestureCompleted( + new AccessibilityGestureInfo(AccessibilityService.GESTURE_SWIPE_UP, + displayId)); case DOWN: - return mListener.onGestureCompleted(AccessibilityService.GESTURE_SWIPE_DOWN); + return mListener.onGestureCompleted( + new AccessibilityGestureInfo(AccessibilityService.GESTURE_SWIPE_DOWN, + displayId)); default: // Do nothing. } @@ -596,7 +599,8 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen int segmentDirection0 = toDirection(dX0, dY0); int segmentDirection1 = toDirection(dX1, dY1); int gestureId = DIRECTIONS_TO_GESTURE_ID[segmentDirection0][segmentDirection1]; - return mListener.onGestureCompleted(gestureId); + return mListener.onGestureCompleted( + new AccessibilityGestureInfo(gestureId, displayId)); } // else if (path.size() < 2 || 3 < path.size()) then no gesture recognized. return mListener.onGestureCancelled(event, policyFlags); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index b6cbbacde118..5111bec4913b 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -114,7 +114,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo private final SparseArray<MagnificationGestureHandler> mMagnificationGestureHandler = new SparseArray<>(0); - private final SparseArray<MotionEventInjector> mMotionEventInjector = new SparseArray<>(0); + private final SparseArray<MotionEventInjector> mMotionEventInjectors = new SparseArray<>(0); private AutoclickController mAutoclickController; @@ -412,12 +412,14 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo MotionEventInjector injector = new MotionEventInjector( mContext.getMainLooper()); addFirstEventHandler(displayId, injector); - // TODO: Need to set MotionEventInjector per display. - mAms.setMotionEventInjector(injector); - mMotionEventInjector.put(displayId, injector); + mMotionEventInjectors.put(displayId, injector); } } + if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) { + mAms.setMotionEventInjectors(mMotionEventInjectors); + } + if ((mEnabledFeatures & FLAG_FEATURE_FILTER_KEY_EVENTS) != 0) { mKeyboardInterceptor = new KeyboardInterceptor(mAms, LocalServices.getService(WindowManagerPolicy.class)); @@ -462,15 +464,14 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } private void disableFeatures() { - for (int i = mMotionEventInjector.size() - 1; i >= 0; i--) { - final MotionEventInjector injector = mMotionEventInjector.valueAt(i); - // TODO: Need to set MotionEventInjector per display. - mAms.setMotionEventInjector(null); + for (int i = mMotionEventInjectors.size() - 1; i >= 0; i--) { + final MotionEventInjector injector = mMotionEventInjectors.valueAt(i); if (injector != null) { injector.onDestroy(); } } - mMotionEventInjector.clear(); + mAms.setMotionEventInjectors(null); + mMotionEventInjectors.clear(); if (mAutoclickController != null) { mAutoclickController.onDestroy(); mAutoclickController = null; diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index a2204518e762..814853694347 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -27,6 +27,7 @@ import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.Manifest; +import android.accessibilityservice.AccessibilityGestureInfo; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.IAccessibilityServiceClient; @@ -210,7 +211,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private KeyEventDispatcher mKeyEventDispatcher; - private MotionEventInjector mMotionEventInjector; + private SparseArray<MotionEventInjector> mMotionEventInjectors; private FingerprintGestureDispatcher mFingerprintGestureDispatcher; @@ -815,11 +816,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } - boolean onGesture(int gestureId) { + boolean onGesture(AccessibilityGestureInfo gestureInfo) { synchronized (mLock) { - boolean handled = notifyGestureLocked(gestureId, false); + boolean handled = notifyGestureLocked(gestureInfo, false); if (!handled) { - handled = notifyGestureLocked(gestureId, true); + handled = notifyGestureLocked(gestureInfo, true); } return handled; } @@ -860,30 +861,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector. * Not using a getter because the AccessibilityInputFilter isn't thread-safe * - * @param motionEventInjector The new value of the motionEventInjector. May be null. + * @param motionEventInjectors The array of motionEventInjectors. May be null. + * */ - void setMotionEventInjector(MotionEventInjector motionEventInjector) { + void setMotionEventInjectors(SparseArray<MotionEventInjector> motionEventInjectors) { synchronized (mLock) { - mMotionEventInjector = motionEventInjector; + mMotionEventInjectors = motionEventInjectors; // We may be waiting on this object being set mLock.notifyAll(); } } @Override - public MotionEventInjector getMotionEventInjectorLocked() { + public @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId) { final long endMillis = SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS; - while ((mMotionEventInjector == null) && (SystemClock.uptimeMillis() < endMillis)) { + MotionEventInjector motionEventInjector = null; + while ((mMotionEventInjectors == null) && (SystemClock.uptimeMillis() < endMillis)) { try { mLock.wait(endMillis - SystemClock.uptimeMillis()); } catch (InterruptedException ie) { /* ignore */ } } - if (mMotionEventInjector == null) { + if (mMotionEventInjectors == null) { Slog.e(LOG_TAG, "MotionEventInjector installation timed out"); + } else { + motionEventInjector = mMotionEventInjectors.get(displayId); } - return mMotionEventInjector; + return motionEventInjector; } /** @@ -1010,7 +1015,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - private boolean notifyGestureLocked(int gestureId, boolean isDefault) { + private boolean notifyGestureLocked(AccessibilityGestureInfo gestureInfo, boolean isDefault) { // TODO: Now we are giving the gestures to the last enabled // service that can handle them which is the last one // in our list since we write the last enabled as the @@ -1024,7 +1029,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { AccessibilityServiceConnection service = state.mBoundServices.get(i); if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { - service.notifyGesture(gestureId); + service.notifyGesture(gestureInfo); return true; } } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java index 02306c02fa6f..961168a46c7d 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java @@ -238,7 +238,6 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect return (userState != null) ? userState.getSoftKeyboardShowMode() : 0; } - @Override public boolean isAccessibilityButtonAvailable() { synchronized (mLock) { @@ -354,12 +353,13 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect } @Override - public void sendGesture(int sequence, ParceledListSlice gestureSteps) { + public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) { + final boolean isTouchableDisplay = mWindowManagerService.isTouchableDisplay(displayId); synchronized (mLock) { if (mSecurityPolicy.canPerformGestures(this)) { MotionEventInjector motionEventInjector = - mSystemSupport.getMotionEventInjectorLocked(); - if (motionEventInjector != null) { + mSystemSupport.getMotionEventInjectorForDisplayLocked(displayId); + if (motionEventInjector != null && isTouchableDisplay) { motionEventInjector.injectEvents( gestureSteps.getList(), mServiceInterface, sequence); } else { diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java index 7920bbb7b179..380e853820ff 100644 --- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java @@ -20,6 +20,7 @@ import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.server.accessibility.TouchState.ALL_POINTER_ID_BITS; +import android.accessibilityservice.AccessibilityGestureInfo; import android.content.Context; import android.graphics.Point; import android.os.Handler; @@ -356,14 +357,14 @@ class TouchExplorer extends BaseEventStreamTransformation } @Override - public boolean onGestureCompleted(int gestureId) { + public boolean onGestureCompleted(AccessibilityGestureInfo gestureInfo) { if (!mState.isGestureDetecting()) { return false; } endGestureDetection(true); - mAms.onGesture(gestureId); + mAms.onGesture(gestureInfo); return true; } diff --git a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java index e68263a51415..813fc8d5f561 100644 --- a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java +++ b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java @@ -64,12 +64,13 @@ public class CustomScrollView extends ScrollView { return; } + mWidth = MeasureSpec.getSize(widthMeasureSpec); calculateDimensions(); setMeasuredDimension(mWidth, mHeight); } private void calculateDimensions() { - if (mWidth != -1) return; + if (mHeight != -1) return; final TypedValue typedValue = new TypedValue(); final Point point = new Point(); @@ -81,7 +82,6 @@ public class CustomScrollView extends ScrollView { final int childHeight = child.getMeasuredHeight(); final int maxHeight = (int) typedValue.getFraction(point.y, point.y); - mWidth = point.x; mHeight = Math.min(childHeight, maxHeight); if (sDebug) { Slog.d(TAG, "calculateDimensions(): maxHeight=" + maxHeight diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index 73f5cb8326ea..e2cdddb932d7 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -165,7 +165,13 @@ final class SaveUi { mComponentName = componentName; mCompatMode = compatMode; - context = new ContextThemeWrapper(context, mThemeId); + context = new ContextThemeWrapper(context, mThemeId) { + @Override + public void startActivity(Intent intent) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + super.startActivity(intent); + } + }; final LayoutInflater inflater = LayoutInflater.from(context); final View view = inflater.inflate(R.layout.autofill_save, null); diff --git a/services/core/Android.bp b/services/core/Android.bp index 9855e4ea339a..474dbfe49d70 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -13,12 +13,14 @@ java_library_static { }, srcs: [ "java/**/*.java", + ":platformcompat_aidl", ":dumpstate_aidl", ":idmap2_aidl", ":installd_aidl", ":storaged_aidl", ":vold_aidl", ":gsiservice_aidl", + ":platform-compat-config", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags", @@ -80,3 +82,11 @@ prebuilt_etc { name: "gps_debug.conf", src: "java/com/android/server/location/gps_debug.conf", } + +filegroup { + name: "platformcompat_aidl", + srcs: [ + "java/com/android/server/compat/IPlatformCompat.aidl", + ], + path: "java", +} diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 188d65494868..208b63888efb 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -1185,7 +1185,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (isBluetoothDisallowed) { return; } - if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { + final boolean isSafeMode = mContext.getPackageManager().isSafeMode(); + if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) { if (DBG) { Slog.d(TAG, "Auto-enabling Bluetooth."); } diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index ddfc3a631be6..a30371876955 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -1742,6 +1742,12 @@ public class DeviceIdleController extends SystemService return mConstants; } + + /** Returns the current elapsed realtime in milliseconds. */ + long getElapsedRealtime() { + return SystemClock.elapsedRealtime(); + } + LocationManager getLocationManager() { if (mLocationManager == null) { mLocationManager = mContext.getSystemService(LocationManager.class); @@ -2023,7 +2029,7 @@ public class DeviceIdleController extends SystemService private void unregisterDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint) { synchronized (this) { - // Artifically force the constraint to inactive to unblock anything waiting for it. + // Artificially force the constraint to inactive to unblock anything waiting for it. onConstraintStateChangedLocked(constraint, /* active= */ false); // Let the constraint know that we are not listening to it any more. @@ -2746,9 +2752,18 @@ public class DeviceIdleController extends SystemService mState = STATE_QUICK_DOZE_DELAY; // Make sure any motion sensing or locating is stopped. resetIdleManagementLocked(); - // Wait a small amount of time in case something (eg: background service from - // recently closed app) needs to finish running. - scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false); + if (isUpcomingAlarmClock()) { + // If there's an upcoming AlarmClock alarm, we won't go into idle, so + // setting a wakeup alarm before the upcoming alarm is futile. Set the quick + // doze alarm to after the upcoming AlarmClock alarm. + scheduleAlarmLocked( + mAlarmManager.getNextWakeFromIdleTime() - mInjector.getElapsedRealtime() + + mConstants.QUICK_DOZE_DELAY_TIMEOUT, false); + } else { + // Wait a small amount of time in case something (eg: background service from + // recently closed app) needs to finish running. + scheduleAlarmLocked(mConstants.QUICK_DOZE_DELAY_TIMEOUT, false); + } EventLogTags.writeDeviceIdle(mState, "no activity"); } else if (mState == STATE_ACTIVE) { mState = STATE_INACTIVE; @@ -2758,7 +2773,16 @@ public class DeviceIdleController extends SystemService if (shouldUseIdleTimeoutFactorLocked()) { delay = (long) (mPreIdleFactor * delay); } - scheduleAlarmLocked(delay, false); + if (isUpcomingAlarmClock()) { + // If there's an upcoming AlarmClock alarm, we won't go into idle, so + // setting a wakeup alarm before the upcoming alarm is futile. Set the idle + // alarm to after the upcoming AlarmClock alarm. + scheduleAlarmLocked( + mAlarmManager.getNextWakeFromIdleTime() - mInjector.getElapsedRealtime() + + delay, false); + } else { + scheduleAlarmLocked(delay, false); + } EventLogTags.writeDeviceIdle(mState, "no activity"); } } @@ -2906,13 +2930,21 @@ public class DeviceIdleController extends SystemService return mState; } + /** + * Returns true if there's an upcoming AlarmClock alarm that is soon enough to prevent the + * device from going into idle. + */ + private boolean isUpcomingAlarmClock() { + return mInjector.getElapsedRealtime() + mConstants.MIN_TIME_TO_ALARM + >= mAlarmManager.getNextWakeFromIdleTime(); + } + @VisibleForTesting void stepIdleStateLocked(String reason) { if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState); EventLogTags.writeDeviceIdleStep(); - final long now = SystemClock.elapsedRealtime(); - if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { + if (isUpcomingAlarmClock()) { // Whoops, there is an upcoming alarm. We don't actually want to go idle. if (mState != STATE_ACTIVE) { mActiveReason = ACTIVE_REASON_ALARM; diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java index 9dead161390f..aeb3e7fd94de 100644 --- a/services/core/java/com/android/server/DropBoxManagerService.java +++ b/services/core/java/com/android/server/DropBoxManagerService.java @@ -41,7 +41,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; -import android.text.format.Time; +import android.text.format.TimeMigrationUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; @@ -582,11 +582,9 @@ public final class DropBoxManagerService extends SystemService { } int numFound = 0, numArgs = searchArgs.size(); - Time time = new Time(); out.append("\n"); for (EntryFile entry : mAllFiles.contents) { - time.set(entry.timestampMillis); - String date = time.format("%Y-%m-%d %H:%M:%S"); + String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis); boolean match = true; for (int i = 0; i < numArgs && match; i++) { String arg = searchArgs.get(i); diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 30a356325ada..b9d7c687704c 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -48,7 +48,6 @@ import android.os.ShellCallback; import android.os.ShellCommand; import android.os.SystemProperties; import android.os.UserHandle; -import android.os.UserManager; import android.provider.Settings.Secure; import android.service.dreams.Sandman; import android.service.vr.IVrManager; @@ -218,6 +217,15 @@ final class UiModeManagerService extends SystemService { } }; + private final ContentObserver mDarkThemeObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange, Uri uri) { + int mode = Secure.getIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, + mNightMode, 0); + SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode)); + } + }; + @Override public void onSwitchUser(int userHandle) { super.onSwitchUser(userHandle); @@ -293,6 +301,9 @@ final class UiModeManagerService extends SystemService { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_SWITCHED); context.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler); + + context.getContentResolver().registerContentObserver(Secure.getUriFor(Secure.UI_NIGHT_MODE), + false, mDarkThemeObserver, 0); } // Records whether setup wizard has happened or not and adds an observer for this user if not. @@ -417,11 +428,6 @@ final class UiModeManagerService extends SystemService { if (!mCarModeEnabled) { Secure.putIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE, mode, user); - - if (UserManager.get(getContext()).isPrimaryUser()) { - SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, - Integer.toString(mode)); - } } mNightMode = mode; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ff8c3e954460..f3264e2be565 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2399,7 +2399,7 @@ public class ActivityManagerService extends IActivityManager.Stub final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */); mProcessList.init(this, activeUids); mLowMemDetector = null; - mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids); + mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, handlerThread); mIntentFirewall = hasHandlerThread ? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null; @@ -7901,11 +7901,12 @@ public class ActivityManagerService extends IActivityManager.Stub } void reportGlobalUsageEventLocked(int event) { - mUsageStatsService.reportEvent("android", mUserController.getCurrentUserId(), event); + mUsageStatsService.reportEvent(Event.DEVICE_EVENT_PACKAGE_NAME, + mUserController.getCurrentUserId(), event); int[] profiles = mUserController.getCurrentProfileIds(); if (profiles != null) { for (int i = profiles.length - 1; i >= 0; i--) { - mUsageStatsService.reportEvent((String)null, profiles[i], event); + mUsageStatsService.reportEvent(Event.DEVICE_EVENT_PACKAGE_NAME, profiles[i], event); } } } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 33070dc6b757..0dd719994de2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -79,7 +79,6 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; -import android.text.format.Time; import android.util.ArrayMap; import android.util.DebugUtils; import android.util.DisplayMetrics; @@ -98,12 +97,16 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URISyntaxException; +import java.time.Clock; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -116,10 +119,14 @@ import javax.microedition.khronos.egl.EGLSurface; final class ActivityManagerShellCommand extends ShellCommand { public static final String NO_CLASS_ERROR_CODE = "Error type 3"; + private static final String SHELL_PACKAGE_NAME = "com.android.shell"; private static final int USER_OPERATION_TIMEOUT_MS = 2 * 60 * 1000; // 2 minutes + private static final DateTimeFormatter LOG_NAME_TIME_FORMATTER = + DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss", Locale.ROOT); + // IPC interface to activity manager -- don't need to do additional security checks. final IActivityManager mInterface; final IActivityTaskManager mTaskInterface; @@ -922,9 +929,9 @@ final class ActivityManagerShellCommand extends ShellCommand { String process = getNextArgRequired(); String heapFile = getNextArg(); if (heapFile == null) { - final Time t = new Time(); - t.set(System.currentTimeMillis()); - heapFile = "/data/local/tmp/heapdump-" + t.format("%Y%m%d-%H%M%S") + ".prof"; + LocalDateTime localDateTime = LocalDateTime.now(Clock.systemDefaultZone()); + String logNameTimeString = LOG_NAME_TIME_FORMATTER.format(localDateTime); + heapFile = "/data/local/tmp/heapdump-" + logNameTimeString + ".prof"; } pw.println("File: " + heapFile); pw.flush(); diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index a2613d87d923..97e529361a46 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -34,6 +34,7 @@ import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE; import static android.os.Process.THREAD_GROUP_DEFAULT; import static android.os.Process.THREAD_GROUP_RESTRICTED; import static android.os.Process.THREAD_GROUP_TOP_APP; +import static android.os.Process.THREAD_PRIORITY_DISPLAY; import static android.os.Process.setProcessGroup; import static android.os.Process.setThreadPriority; import static android.os.Process.setThreadScheduler; @@ -162,6 +163,21 @@ public final class OomAdjuster { private final ProcessList mProcessList; OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) { + this(service, processList, activeUids, createAdjusterThread()); + } + + private static ServiceThread createAdjusterThread() { + // The process group is usually critical to the response time of foreground app, so the + // setter should apply it as soon as possible. + final ServiceThread adjusterThread = + new ServiceThread(TAG, TOP_APP_PRIORITY_BOOST, false /* allowIo */); + adjusterThread.start(); + Process.setThreadGroupAndCpuset(adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP); + return adjusterThread; + } + + OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids, + ServiceThread adjusterThread) { mService = service; mProcessList = processList; mActiveUids = activeUids; @@ -170,12 +186,6 @@ public final class OomAdjuster { mConstants = mService.mConstants; mAppCompact = new AppCompactor(mService); - // The process group is usually critical to the response time of foreground app, so the - // setter should apply it as soon as possible. - final ServiceThread adjusterThread = new ServiceThread(TAG, TOP_APP_PRIORITY_BOOST, - false /* allowIo */); - adjusterThread.start(); - Process.setThreadGroupAndCpuset(adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP); mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> { final int pid = msg.arg1; final int group = msg.arg2; @@ -1806,7 +1816,6 @@ public final class OomAdjuster { if (app.renderThreadTid != 0) { setThreadScheduler(app.renderThreadTid, SCHED_OTHER, 0); - setThreadPriority(app.renderThreadTid, -4); } } catch (IllegalArgumentException e) { Slog.w(TAG, @@ -1818,9 +1827,10 @@ public final class OomAdjuster { } else { // Reset priority for top app UI and render threads setThreadPriority(app.pid, 0); - if (app.renderThreadTid != 0) { - setThreadPriority(app.renderThreadTid, 0); - } + } + + if (app.renderThreadTid != 0) { + setThreadPriority(app.renderThreadTid, THREAD_PRIORITY_DISPLAY); } } } catch (Exception e) { diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index bd3cd5439b32..af2f24f959b4 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -789,6 +789,23 @@ public class BiometricService extends SystemService { return error; } + @Override + public boolean hasEnrolledBiometrics(int userId) { + checkInternalPermission(); + + final long ident = Binder.clearCallingIdentity(); + try { + for (int i = 0; i < mAuthenticators.size(); i++) { + if (mAuthenticators.get(i).mAuthenticator.hasEnrolledTemplates(userId)) { + return true; + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + return false; + } + @Override // Binder call public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) throws RemoteException { diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java index 20eb6180832c..f3f9754bd32b 100644 --- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java +++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java @@ -282,10 +282,10 @@ public abstract class BiometricServiceBase extends SystemService public EnrollClientImpl(Context context, DaemonWrapper daemon, long halDeviceId, IBinder token, ServiceListener listener, int userId, int groupId, byte[] cryptoToken, boolean restricted, String owner, - final int[] disabledFeatures) { + final int[] disabledFeatures, int timeoutSec) { super(context, getConstants(), daemon, halDeviceId, token, listener, userId, groupId, cryptoToken, restricted, owner, getBiometricUtils(), - disabledFeatures); + disabledFeatures, timeoutSec); } @Override @@ -912,8 +912,12 @@ public abstract class BiometricServiceBase extends SystemService } protected void setActiveUserInternal(int userId) { - // Do not put on handler, since it should finish before returning to caller. - updateActiveGroup(userId, null /* clientPackage */); + mHandler.post(() -> { + if (DEBUG) { + Slog.d(getTag(), "setActiveUser(" + userId + ")"); + } + updateActiveGroup(userId, null /* clientPackage */); + }); } protected void removeInternal(RemovalClient client) { diff --git a/services/core/java/com/android/server/biometrics/EnrollClient.java b/services/core/java/com/android/server/biometrics/EnrollClient.java index 854528f0654d..7ebb7c059b4c 100644 --- a/services/core/java/com/android/server/biometrics/EnrollClient.java +++ b/services/core/java/com/android/server/biometrics/EnrollClient.java @@ -31,11 +31,11 @@ import java.util.Arrays; * A class to keep track of the enrollment state for a given client. */ public abstract class EnrollClient extends ClientMonitor { - private static final long MS_PER_SEC = 1000; - private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute private final byte[] mCryptoToken; private final BiometricUtils mBiometricUtils; private final int[] mDisabledFeatures; + private final int mTimeoutSec; + private long mEnrollmentStartTimeMs; public abstract boolean shouldVibrate(); @@ -44,12 +44,13 @@ public abstract class EnrollClient extends ClientMonitor { BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token, BiometricServiceBase.ServiceListener listener, int userId, int groupId, byte[] cryptoToken, boolean restricted, String owner, BiometricUtils utils, - final int[] disabledFeatures) { + final int[] disabledFeatures, int timeoutSec) { super(context, constants, daemon, halDeviceId, token, listener, userId, groupId, restricted, owner, 0 /* cookie */); mBiometricUtils = utils; mCryptoToken = Arrays.copyOf(cryptoToken, cryptoToken.length); mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length); + mTimeoutSec = timeoutSec; } @Override @@ -94,14 +95,13 @@ public abstract class EnrollClient extends ClientMonitor { @Override public int start() { mEnrollmentStartTimeMs = System.currentTimeMillis(); - final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); try { final ArrayList<Integer> disabledFeatures = new ArrayList<>(); for (int i = 0; i < mDisabledFeatures.length; i++) { disabledFeatures.add(mDisabledFeatures[i]); } - final int result = getDaemonWrapper().enroll(mCryptoToken, getGroupId(), timeout, + final int result = getDaemonWrapper().enroll(mCryptoToken, getGroupId(), mTimeoutSec, disabledFeatures); if (result != 0) { Slog.w(getLogTag(), "startEnroll failed, result=" + result); diff --git a/services/core/java/com/android/server/biometrics/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/LoggableMonitor.java index 6c7cbc166241..ecf3864e3362 100644 --- a/services/core/java/com/android/server/biometrics/LoggableMonitor.java +++ b/services/core/java/com/android/server/biometrics/LoggableMonitor.java @@ -93,7 +93,7 @@ public abstract class LoggableMonitor { statsAction(), statsClient(), acquiredInfo, - 0 /* vendorCode */, // Don't log vendorCode for now + vendorCode, Utils.isDebugEnabled(context, targetUserId)); } diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java index a38abdc1bed0..a7065216f6a3 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -329,6 +329,7 @@ public class FaceService extends BiometricServiceBase { * Receives the incoming binder calls from FaceManager. */ private final class FaceServiceWrapper extends IFaceService.Stub { + private static final int ENROLL_TIMEOUT_SEC = 75; /** * The following methods contain common code which is shared in biometrics/common. @@ -343,16 +344,19 @@ public class FaceService extends BiometricServiceBase { @Override // Binder call public int revokeChallenge(IBinder token) { checkPermission(MANAGE_BIOMETRIC); - // TODO(b/137106905): Schedule binder calls in FaceService to avoid deadlocks. - if (getCurrentClient() == null) { - // if we aren't handling any other HIDL calls (mCurrentClient == null), revoke the - // challenge right away. - return startRevokeChallenge(token); - } else { - // postpone revoking the challenge until we finish processing the current HIDL call. - mRevokeChallengePending = true; - return Status.OK; - } + mHandler.post(() -> { + // TODO(b/137106905): Schedule binder calls in FaceService to avoid deadlocks. + if (getCurrentClient() == null) { + // if we aren't handling any other HIDL calls (mCurrentClient == null), revoke + // the challenge right away. + startRevokeChallenge(token); + } else { + // postpone revoking the challenge until we finish processing the current HIDL + // call. + mRevokeChallengePending = true; + } + }); + return Status.OK; } @Override // Binder call @@ -368,7 +372,8 @@ public class FaceService extends BiometricServiceBase { final boolean restricted = isRestricted(); final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, - 0 /* groupId */, cryptoToken, restricted, opPackageName, disabledFeatures) { + 0 /* groupId */, cryptoToken, restricted, opPackageName, disabledFeatures, + ENROLL_TIMEOUT_SEC) { @Override public int[] getAcquireIgnorelist() { @@ -609,27 +614,32 @@ public class FaceService extends BiometricServiceBase { public void resetLockout(byte[] token) { checkPermission(MANAGE_BIOMETRIC); - if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) { - Slog.w(TAG, "Ignoring lockout reset, no templates enrolled"); - return; - } + mHandler.post(() -> { + if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) { + Slog.w(TAG, "Ignoring lockout reset, no templates enrolled"); + return; + } - Slog.d(TAG, "Resetting lockout for user: " + mCurrentUserId); + Slog.d(TAG, "Resetting lockout for user: " + mCurrentUserId); - try { - mDaemonWrapper.resetLockout(token); - } catch (RemoteException e) { - Slog.e(getTag(), "Unable to reset lockout", e); - } + try { + mDaemonWrapper.resetLockout(token); + } catch (RemoteException e) { + Slog.e(getTag(), "Unable to reset lockout", e); + } + }); } @Override public void setFeature(int userId, int feature, boolean enabled, final byte[] token, IFaceServiceReceiver receiver, final String opPackageName) { checkPermission(MANAGE_BIOMETRIC); - updateActiveGroup(userId, opPackageName); mHandler.post(() -> { + if (DEBUG) { + Slog.d(TAG, "setFeature for user(" + userId + ")"); + } + updateActiveGroup(userId, opPackageName); if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) { Slog.e(TAG, "No enrolled biometrics while setting feature: " + feature); return; @@ -660,9 +670,12 @@ public class FaceService extends BiometricServiceBase { public void getFeature(int userId, int feature, IFaceServiceReceiver receiver, final String opPackageName) { checkPermission(MANAGE_BIOMETRIC); - updateActiveGroup(userId, opPackageName); mHandler.post(() -> { + if (DEBUG) { + Slog.d(TAG, "getFeature for user(" + userId + ")"); + } + updateActiveGroup(userId, opPackageName); // This should ideally return tri-state, but the user isn't shown settings unless // they are enrolled so it's fine for now. if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) { diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java index 28336f459863..320e1022873c 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -176,6 +176,7 @@ public class FingerprintService extends BiometricServiceBase { * Receives the incoming binder calls from FingerprintManager. */ private final class FingerprintServiceWrapper extends IFingerprintService.Stub { + private static final int ENROLL_TIMEOUT_SEC = 60; /** * The following methods contain common code which is shared in biometrics/common. @@ -203,7 +204,8 @@ public class FingerprintService extends BiometricServiceBase { final int groupId = userId; // default group for fingerprint enrollment final EnrollClientImpl client = new EnrollClientImpl(getContext(), mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver), mCurrentUserId, groupId, - cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */) { + cryptoToken, restricted, opPackageName, new int[0] /* disabledFeatures */, + ENROLL_TIMEOUT_SEC) { @Override public boolean shouldVibrate() { return true; diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java index 9730c9a1a380..1a1845ac3d5f 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java @@ -28,7 +28,6 @@ import android.hardware.broadcastradio.V2_0.MetadataKey; import android.hardware.broadcastradio.V2_0.ProgramFilter; import android.hardware.broadcastradio.V2_0.ProgramIdentifier; import android.hardware.broadcastradio.V2_0.ProgramInfo; -import android.hardware.broadcastradio.V2_0.ProgramInfoFlags; import android.hardware.broadcastradio.V2_0.ProgramListChunk; import android.hardware.broadcastradio.V2_0.Properties; import android.hardware.broadcastradio.V2_0.Result; diff --git a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java index b1bd39566ba6..8c9389101141 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java @@ -48,6 +48,10 @@ class ProgramInfoCache { private final Map<ProgramSelector.Identifier, RadioManager.ProgramInfo> mProgramInfoMap = new HashMap<>(); + // Flag indicating whether mProgramInfoMap is considered complete based upon the received + // updates. + private boolean mComplete = true; + // Optional filter used in filterAndUpdateFrom(). Usually this field is null for a HAL-side // cache and non-null for an AIDL-side cache. private final ProgramList.Filter mFilter; @@ -58,9 +62,10 @@ class ProgramInfoCache { // Constructor for testing. @VisibleForTesting - ProgramInfoCache(@Nullable ProgramList.Filter filter, + ProgramInfoCache(@Nullable ProgramList.Filter filter, boolean complete, RadioManager.ProgramInfo... programInfos) { mFilter = filter; + mComplete = complete; for (RadioManager.ProgramInfo programInfo : programInfos) { mProgramInfoMap.put(programInfo.getSelector().getPrimaryId(), programInfo); } @@ -77,15 +82,23 @@ class ProgramInfoCache { @Override public String toString() { - StringBuilder sb = new StringBuilder("ProgramInfoCache("); + StringBuilder sb = new StringBuilder("ProgramInfoCache(mComplete = "); + sb.append(mComplete); + sb.append(", mFilter = "); + sb.append(mFilter); + sb.append(", mProgramInfoMap = ["); mProgramInfoMap.forEach((id, programInfo) -> { sb.append("\n"); sb.append(programInfo.toString()); }); - sb.append(")"); + sb.append("]"); return sb.toString(); } + public boolean isComplete() { + return mComplete; + } + public @Nullable ProgramList.Filter getFilter() { return mFilter; } @@ -102,6 +115,7 @@ class ProgramInfoCache { for (android.hardware.broadcastradio.V2_0.ProgramIdentifier halProgramId : chunk.removed) { mProgramInfoMap.remove(Convert.programIdentifierFromHal(halProgramId)); } + mComplete = chunk.complete; } @NonNull List<ProgramList.Chunk> filterAndUpdateFrom(@NonNull ProgramInfoCache other, @@ -122,26 +136,18 @@ class ProgramInfoCache { purge = true; } - Set<Integer> idTypes = mFilter != null ? mFilter.getIdentifierTypes() : null; - Set<ProgramSelector.Identifier> ids = mFilter != null ? mFilter.getIdentifiers() : null; - boolean includeCategories = mFilter != null ? mFilter.areCategoriesIncluded() : true; - boolean includeModifications = mFilter != null ? !mFilter.areModificationsExcluded() : true; - Set<RadioManager.ProgramInfo> modified = new HashSet<>(); Set<ProgramSelector.Identifier> removed = new HashSet<>(mProgramInfoMap.keySet()); for (Map.Entry<ProgramSelector.Identifier, RadioManager.ProgramInfo> entry : other.mProgramInfoMap.entrySet()) { ProgramSelector.Identifier id = entry.getKey(); - if ((idTypes != null && !idTypes.isEmpty() && !idTypes.contains(id.getType())) - || (ids != null && !ids.isEmpty() && !ids.contains(id)) - || (!includeCategories && id.isCategoryType())) { + if (!passesFilter(id)) { continue; } - removed.remove(id); - RadioManager.ProgramInfo oldInfo = mProgramInfoMap.get(id); + RadioManager.ProgramInfo newInfo = entry.getValue(); - if (oldInfo != null && (!includeModifications || oldInfo.equals(newInfo))) { + if (!shouldIncludeInModified(newInfo)) { continue; } mProgramInfoMap.put(id, newInfo); @@ -150,14 +156,81 @@ class ProgramInfoCache { for (ProgramSelector.Identifier rem : removed) { mProgramInfoMap.remove(rem); } - return buildChunks(purge, modified, maxNumModifiedPerChunk, removed, maxNumRemovedPerChunk); + mComplete = other.mComplete; + return buildChunks(purge, mComplete, modified, maxNumModifiedPerChunk, removed, + maxNumRemovedPerChunk); + } + + @Nullable List<ProgramList.Chunk> filterAndApplyChunk(@NonNull ProgramList.Chunk chunk) { + return filterAndApplyChunkInternal(chunk, MAX_NUM_MODIFIED_PER_CHUNK, + MAX_NUM_REMOVED_PER_CHUNK); + } + + @VisibleForTesting + @Nullable List<ProgramList.Chunk> filterAndApplyChunkInternal(@NonNull ProgramList.Chunk chunk, + int maxNumModifiedPerChunk, int maxNumRemovedPerChunk) { + if (chunk.isPurge()) { + mProgramInfoMap.clear(); + } + + Set<RadioManager.ProgramInfo> modified = new HashSet<>(); + Set<ProgramSelector.Identifier> removed = new HashSet<>(); + for (RadioManager.ProgramInfo info : chunk.getModified()) { + ProgramSelector.Identifier id = info.getSelector().getPrimaryId(); + if (!passesFilter(id) || !shouldIncludeInModified(info)) { + continue; + } + mProgramInfoMap.put(id, info); + modified.add(info); + } + for (ProgramSelector.Identifier id : chunk.getRemoved()) { + if (mProgramInfoMap.containsKey(id)) { + mProgramInfoMap.remove(id); + removed.add(id); + } + } + if (modified.isEmpty() && removed.isEmpty() && mComplete == chunk.isComplete()) { + return null; + } + mComplete = chunk.isComplete(); + return buildChunks(chunk.isPurge(), mComplete, modified, maxNumModifiedPerChunk, removed, + maxNumRemovedPerChunk); + } + + private boolean passesFilter(ProgramSelector.Identifier id) { + if (mFilter == null) { + return true; + } + if (!mFilter.getIdentifierTypes().isEmpty() + && !mFilter.getIdentifierTypes().contains(id.getType())) { + return false; + } + if (!mFilter.getIdentifiers().isEmpty() && !mFilter.getIdentifiers().contains(id)) { + return false; + } + if (!mFilter.areCategoriesIncluded() && id.isCategoryType()) { + return false; + } + return true; + } + + private boolean shouldIncludeInModified(RadioManager.ProgramInfo newInfo) { + RadioManager.ProgramInfo oldInfo = mProgramInfoMap.get( + newInfo.getSelector().getPrimaryId()); + if (oldInfo == null) { + return true; + } + if (mFilter != null && mFilter.areModificationsExcluded()) { + return false; + } + return !oldInfo.equals(newInfo); } private static int roundUpFraction(int numerator, int denominator) { return (numerator / denominator) + (numerator % denominator > 0 ? 1 : 0); } - private @NonNull List<ProgramList.Chunk> buildChunks(boolean purge, + private static @NonNull List<ProgramList.Chunk> buildChunks(boolean purge, boolean complete, @Nullable Collection<RadioManager.ProgramInfo> modified, int maxNumModifiedPerChunk, @Nullable Collection<ProgramSelector.Identifier> removed, int maxNumRemovedPerChunk) { // Communication protocol requires that if purge is set, removed is empty. @@ -205,8 +278,8 @@ class ProgramInfoCache { removedChunk.add(removedIter.next()); } } - chunks.add(new ProgramList.Chunk(purge && i == 0, i == numChunks - 1, modifiedChunk, - removedChunk)); + chunks.add(new ProgramList.Chunk(purge && i == 0, complete && (i == numChunks - 1), + modifiedChunk, removedChunk)); } return chunks; } diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java index acb0207ff11f..53890a48a674 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java @@ -40,6 +40,7 @@ import android.util.MutableInt; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.HashSet; @@ -64,7 +65,13 @@ class RadioModule { private Boolean mAntennaConnected = null; @GuardedBy("mLock") - private RadioManager.ProgramInfo mProgramInfo = null; + private RadioManager.ProgramInfo mCurrentProgramInfo = null; + + @GuardedBy("mLock") + private final ProgramInfoCache mProgramInfoCache = new ProgramInfoCache(null); + + @GuardedBy("mLock") + private android.hardware.radio.ProgramList.Filter mUnionOfAidlProgramFilters = null; // Callback registered with the HAL to relay callbacks to AIDL clients. private final ITunerCallback mHalTunerCallback = new ITunerCallback.Stub() { @@ -78,17 +85,22 @@ class RadioModule { public void onCurrentProgramInfoChanged(ProgramInfo halProgramInfo) { RadioManager.ProgramInfo programInfo = Convert.programInfoFromHal(halProgramInfo); synchronized (mLock) { - mProgramInfo = programInfo; + mCurrentProgramInfo = programInfo; fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(programInfo)); } } @Override public void onProgramListUpdated(ProgramListChunk programListChunk) { - // TODO: Cache per-AIDL client filters, send union of filters to HAL, use filters to fan - // back out to clients. - fanoutAidlCallback(cb -> cb.onProgramListUpdated(Convert.programListChunkFromHal( - programListChunk))); + synchronized (mLock) { + android.hardware.radio.ProgramList.Chunk chunk = + Convert.programListChunkFromHal(programListChunk); + mProgramInfoCache.filterAndApplyChunk(chunk); + + for (TunerSession tunerSession : mAidlTunerSessions) { + tunerSession.onMergedProgramListUpdateFromHal(chunk); + } + } } @Override @@ -109,8 +121,9 @@ class RadioModule { @GuardedBy("mLock") private final Set<TunerSession> mAidlTunerSessions = new HashSet<>(); - private RadioModule(@NonNull IBroadcastRadio service, - @NonNull RadioManager.ModuleProperties properties) throws RemoteException { + @VisibleForTesting + RadioModule(@NonNull IBroadcastRadio service, + @NonNull RadioManager.ModuleProperties properties) { mProperties = Objects.requireNonNull(properties); mService = Objects.requireNonNull(service); } @@ -163,8 +176,8 @@ class RadioModule { if (mAntennaConnected != null) { userCb.onAntennaState(mAntennaConnected); } - if (mProgramInfo != null) { - userCb.onCurrentProgramInfoChanged(mProgramInfo); + if (mCurrentProgramInfo != null) { + userCb.onCurrentProgramInfoChanged(mCurrentProgramInfo); } return tunerSession; @@ -186,18 +199,114 @@ class RadioModule { } } + private @Nullable android.hardware.radio.ProgramList.Filter + buildUnionOfTunerSessionFiltersLocked() { + Set<Integer> idTypes = null; + Set<android.hardware.radio.ProgramSelector.Identifier> ids = null; + boolean includeCategories = false; + boolean excludeModifications = true; + + for (TunerSession tunerSession : mAidlTunerSessions) { + android.hardware.radio.ProgramList.Filter filter = + tunerSession.getProgramListFilter(); + if (filter == null) { + continue; + } + + if (idTypes == null) { + idTypes = new HashSet<>(filter.getIdentifierTypes()); + ids = new HashSet<>(filter.getIdentifiers()); + includeCategories = filter.areCategoriesIncluded(); + excludeModifications = filter.areModificationsExcluded(); + continue; + } + if (!idTypes.isEmpty()) { + if (filter.getIdentifierTypes().isEmpty()) { + idTypes.clear(); + } else { + idTypes.addAll(filter.getIdentifierTypes()); + } + } + + if (!ids.isEmpty()) { + if (filter.getIdentifiers().isEmpty()) { + ids.clear(); + } else { + ids.addAll(filter.getIdentifiers()); + } + } + + includeCategories |= filter.areCategoriesIncluded(); + excludeModifications &= filter.areModificationsExcluded(); + } + + return idTypes == null ? null : new android.hardware.radio.ProgramList.Filter(idTypes, ids, + includeCategories, excludeModifications); + } + + void onTunerSessionProgramListFilterChanged(@Nullable TunerSession session) { + synchronized (mLock) { + onTunerSessionProgramListFilterChangedLocked(session); + } + } + + private void onTunerSessionProgramListFilterChangedLocked(@Nullable TunerSession session) { + android.hardware.radio.ProgramList.Filter newFilter = + buildUnionOfTunerSessionFiltersLocked(); + if (newFilter == null) { + // If there are no AIDL clients remaining, we can stop updates from the HAL as well. + if (mUnionOfAidlProgramFilters == null) { + return; + } + mUnionOfAidlProgramFilters = null; + try { + mHalTunerSession.stopProgramListUpdates(); + } catch (RemoteException ex) { + Slog.e(TAG, "mHalTunerSession.stopProgramListUpdates() failed: ", ex); + } + return; + } + + // If the HAL filter doesn't change, we can immediately send an update to the AIDL + // client. + if (newFilter.equals(mUnionOfAidlProgramFilters)) { + if (session != null) { + session.updateProgramInfoFromHalCache(mProgramInfoCache); + } + return; + } + + // Otherwise, update the HAL's filter, and AIDL clients will be updated when + // mHalTunerCallback.onProgramListUpdated() is called. + mUnionOfAidlProgramFilters = newFilter; + try { + int halResult = mHalTunerSession.startProgramListUpdates(Convert.programFilterToHal( + newFilter)); + Convert.throwOnError("startProgramListUpdates", halResult); + } catch (RemoteException ex) { + Slog.e(TAG, "mHalTunerSession.startProgramListUpdates() failed: ", ex); + } + } + void onTunerSessionClosed(TunerSession tunerSession) { synchronized (mLock) { + onTunerSessionsClosedLocked(tunerSession); + } + } + + private void onTunerSessionsClosedLocked(TunerSession... tunerSessions) { + for (TunerSession tunerSession : tunerSessions) { mAidlTunerSessions.remove(tunerSession); - if (mAidlTunerSessions.isEmpty() && mHalTunerSession != null) { - Slog.v(TAG, "closing HAL tuner session"); - try { - mHalTunerSession.close(); - } catch (RemoteException ex) { - Slog.e(TAG, "mHalTunerSession.close() failed: ", ex); - } - mHalTunerSession = null; + } + onTunerSessionProgramListFilterChanged(null); + if (mAidlTunerSessions.isEmpty() && mHalTunerSession != null) { + Slog.v(TAG, "closing HAL tuner session"); + try { + mHalTunerSession.close(); + } catch (RemoteException ex) { + Slog.e(TAG, "mHalTunerSession.close() failed: ", ex); } + mHalTunerSession = null; } } @@ -213,18 +322,25 @@ class RadioModule { } private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) { + List<TunerSession> deadSessions = null; for (TunerSession tunerSession : mAidlTunerSessions) { try { runnable.run(tunerSession.mCallback); } catch (DeadObjectException ex) { - // The other side died without calling close(), so just purge it from our - // records. + // The other side died without calling close(), so just purge it from our records. Slog.e(TAG, "Removing dead TunerSession"); - mAidlTunerSessions.remove(tunerSession); + if (deadSessions == null) { + deadSessions = new ArrayList<>(); + } + deadSessions.add(tunerSession); } catch (RemoteException ex) { Slog.e(TAG, "Failed to invoke ITunerCallback: ", ex); } } + if (deadSessions != null) { + onTunerSessionsClosedLocked(deadSessions.toArray( + new TunerSession[deadSessions.size()])); + } } public android.hardware.radio.ICloseHandle addAnnouncementListener(@NonNull int[] enabledTypes, diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java index 008fea5831ad..764fca9a66b2 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java @@ -46,6 +46,7 @@ class TunerSession extends ITuner.Stub { final android.hardware.radio.ITunerCallback mCallback; private boolean mIsClosed = false; private boolean mIsMuted = false; + private ProgramInfoCache mProgramInfoCache = null; // necessary only for older APIs compatibility private RadioManager.BandConfig mDummyConfig = null; @@ -187,8 +188,51 @@ class TunerSession extends ITuner.Stub { public void startProgramListUpdates(ProgramList.Filter filter) throws RemoteException { synchronized (mLock) { checkNotClosedLocked(); - int halResult = mHwSession.startProgramListUpdates(Convert.programFilterToHal(filter)); - Convert.throwOnError("startProgramListUpdates", halResult); + mProgramInfoCache = new ProgramInfoCache(filter); + } + // Note: RadioModule.onTunerSessionProgramListFilterChanged() must be called without mLock + // held since it can call getProgramListFilter() and onHalProgramInfoUpdated(). + mModule.onTunerSessionProgramListFilterChanged(this); + } + + ProgramList.Filter getProgramListFilter() { + synchronized (mLock) { + return mProgramInfoCache == null ? null : mProgramInfoCache.getFilter(); + } + } + + void onMergedProgramListUpdateFromHal(ProgramList.Chunk mergedChunk) { + List<ProgramList.Chunk> clientUpdateChunks = null; + synchronized (mLock) { + if (mProgramInfoCache == null) { + return; + } + clientUpdateChunks = mProgramInfoCache.filterAndApplyChunk(mergedChunk); + } + dispatchClientUpdateChunks(clientUpdateChunks); + } + + void updateProgramInfoFromHalCache(ProgramInfoCache halCache) { + List<ProgramList.Chunk> clientUpdateChunks = null; + synchronized (mLock) { + if (mProgramInfoCache == null) { + return; + } + clientUpdateChunks = mProgramInfoCache.filterAndUpdateFrom(halCache, true); + } + dispatchClientUpdateChunks(clientUpdateChunks); + } + + private void dispatchClientUpdateChunks(@Nullable List<ProgramList.Chunk> chunks) { + if (chunks == null) { + return; + } + for (ProgramList.Chunk chunk : chunks) { + try { + mCallback.onProgramListUpdated(chunk); + } catch (RemoteException ex) { + Slog.w(TAG, "mCallback.onProgramListUpdated() failed: ", ex); + } } } @@ -196,8 +240,11 @@ class TunerSession extends ITuner.Stub { public void stopProgramListUpdates() throws RemoteException { synchronized (mLock) { checkNotClosedLocked(); - mHwSession.stopProgramListUpdates(); + mProgramInfoCache = null; } + // Note: RadioModule.onTunerSessionProgramListFilterChanged() must be called without mLock + // held since it can call getProgramListFilter() and onHalProgramInfoUpdated(). + mModule.onTunerSessionProgramListFilterChanged(this); } @Override diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index bb3b9be2bd2f..6f32beea66d3 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -20,6 +20,8 @@ import android.annotation.Nullable; import android.compat.annotation.EnabledAfter; import android.content.pm.ApplicationInfo; +import com.android.server.compat.config.Change; + import java.util.HashMap; import java.util.Map; @@ -60,6 +62,16 @@ public final class CompatChange { mDisabled = disabled; } + /** + * @param change an object generated by services/core/xsd/platform-compat-config.xsd + */ + public CompatChange(Change change) { + mChangeId = change.getId(); + mName = change.getName(); + mEnableAfterTargetSdk = change.getEnableAfterTargetSdk(); + mDisabled = change.getDisabled(); + } + long getId() { return mChangeId; } @@ -106,6 +118,12 @@ public final class CompatChange { * @return {@code true} if the change should be enabled for the package. */ boolean isEnabled(ApplicationInfo app) { + if (app.isSystemApp()) { + // All changes are enabled for system apps, and we do not support overrides. + // Compatibility issues for system apps should be addressed in the app itself when + // the compatibility change is made. + return true; + } if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) { return mPackageOverrides.get(app.packageName); } diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index bcf1d80781a6..044e41789bb2 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -17,13 +17,27 @@ package com.android.server.compat; import android.content.pm.ApplicationInfo; +import android.os.Environment; import android.text.TextUtils; import android.util.LongArray; import android.util.LongSparseArray; +import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.compat.config.Change; +import com.android.server.compat.config.XmlParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; + +import javax.xml.datatype.DatatypeConfigurationException; /** * This class maintains state relating to platform compatibility changes. * @@ -32,7 +46,12 @@ import com.android.internal.annotations.VisibleForTesting; */ public final class CompatConfig { - private static final CompatConfig sInstance = new CompatConfig(); + private static final String TAG = "CompatConfig"; + private static final String CONFIG_FILE_SUFFIX = "platform_compat_config.xml"; + + private static final CompatConfig sInstance = new CompatConfig().initConfigFromLib( + Environment.buildPath( + Environment.getRootDirectory(), "etc", "sysconfig")); @GuardedBy("mChanges") private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>(); @@ -169,4 +188,47 @@ public final class CompatConfig { return overrideExists; } + /** + * Dumps the current list of compatibility config information. + * + * @param pw The {@link PrintWriter} instance to which the information will be dumped. + */ + public void dumpConfig(PrintWriter pw) { + synchronized (mChanges) { + if (mChanges.size() == 0) { + pw.println("No compat overrides."); + return; + } + for (int i = 0; i < mChanges.size(); ++i) { + CompatChange c = mChanges.valueAt(i); + pw.println(c.toString()); + } + } + } + + CompatConfig initConfigFromLib(File libraryDir) { + if (!libraryDir.exists() || !libraryDir.isDirectory()) { + Slog.e(TAG, "No directory " + libraryDir + ", skipping"); + return this; + } + for (File f : libraryDir.listFiles()) { + //TODO(b/138222363): Handle duplicate ids across config files. + if (f.getPath().endsWith(CONFIG_FILE_SUFFIX)) { + readConfig(f); + } + } + return this; + } + + private void readConfig(File configFile) { + try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) { + for (Change change : XmlParser.read(in).getCompatChange()) { + Slog.w(TAG, "Adding: " + change.toString()); + addChange(new CompatChange(change)); + } + } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) { + Slog.e(TAG, "Encountered an error while reading/parsing compat config file", e); + } + } + } diff --git a/services/core/java/com/android/server/compat/IPlatformCompat.aidl b/services/core/java/com/android/server/compat/IPlatformCompat.aidl new file mode 100644 index 000000000000..8ab08f9047cb --- /dev/null +++ b/services/core/java/com/android/server/compat/IPlatformCompat.aidl @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.compat; + +import android.content.pm.ApplicationInfo; + +/** + * System private API for talking with the PlatformCompat service. + * {@hide} + */ +interface IPlatformCompat +{ + + /** + * Reports that a compatibility change is affecting an app process now. + * + * <p>Note: for changes that are gated using {@link #isChangeEnabled(long, ApplicationInfo)}, + * you do not need to call this API directly. The change will be reported for you in the case + * that {@link #isChangeEnabled(long, ApplicationInfo)} returns {@code true}. + * + * @param changeId The ID of the compatibility change taking effect. + * @param appInfo Representing the affected app. + */ + void reportChange(long changeId, in ApplicationInfo appInfo); + + /** + * Query if a given compatibility change is enabled for an app process. This method should + * be called when implementing functionality on behalf of the affected app. + * + * <p>If this method returns {@code true}, the calling code should implement the compatibility + * change, resulting in differing behaviour compared to earlier releases. If this method returns + * {@code false}, the calling code should behave as it did in earlier releases. + * + * <p>When this method returns {@code true}, it will also report the change as + * {@link #reportChange(long, ApplicationInfo)} would, so there is no need to call that method + * directly. + * + * @param changeId The ID of the compatibility change in question. + * @param appInfo Representing the app in question. + * @return {@code true} if the change is enabled for the current app. + */ + boolean isChangeEnabled(long changeId, in ApplicationInfo appInfo); +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 456d15e4fba8..3eea194fd73e 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -16,52 +16,46 @@ package com.android.server.compat; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.util.Slog; +import com.android.internal.util.DumpUtils; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + /** * System server internal API for gating and reporting compatibility changes. */ -public class PlatformCompat { +public class PlatformCompat extends IPlatformCompat.Stub { private static final String TAG = "Compatibility"; - /** - * Reports that a compatibility change is affecting an app process now. - * - * <p>Note: for changes that are gated using {@link #isChangeEnabled(long, ApplicationInfo)}, - * you do not need to call this API directly. The change will be reported for you in the case - * that {@link #isChangeEnabled(long, ApplicationInfo)} returns {@code true}. - * - * @param changeId The ID of the compatibility change taking effect. - * @param appInfo Representing the affected app. - */ - public static void reportChange(long changeId, ApplicationInfo appInfo) { + private final Context mContext; + + public PlatformCompat(Context context) { + mContext = context; + } + + @Override + public void reportChange(long changeId, ApplicationInfo appInfo) { Slog.d(TAG, "Compat change reported: " + changeId + "; UID " + appInfo.uid); // TODO log via StatsLog } - /** - * Query if a given compatibility change is enabled for an app process. This method should - * be called when implementing functionality on behalf of the affected app. - * - * <p>If this method returns {@code true}, the calling code should implement the compatibility - * change, resulting in differing behaviour compared to earlier releases. If this method returns - * {@code false}, the calling code should behave as it did in earlier releases. - * - * <p>When this method returns {@code true}, it will also report the change as - * {@link #reportChange(long, ApplicationInfo)} would, so there is no need to call that method - * directly. - * - * @param changeId The ID of the compatibility change in question. - * @param appInfo Representing the app in question. - * @return {@code true} if the change is enabled for the current app. - */ - public static boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { + @Override + public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { if (CompatConfig.get().isChangeEnabled(changeId, appInfo)) { reportChange(changeId, appInfo); return true; } return false; } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; + CompatConfig.get().dumpConfig(pw); + } } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 64a05c94e39e..f6c49ed4d29e 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -86,7 +86,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.provider.Settings; -import android.text.format.Time; +import android.text.format.TimeMigrationUtils; import android.util.EventLog; import android.util.Log; import android.util.Pair; @@ -1993,9 +1993,7 @@ public class SyncManager { if (time == 0) { return "N/A"; } - Time tobj = new Time(); - tobj.set(time); - return tobj.format("%Y-%m-%d %H:%M:%S"); + return TimeMigrationUtils.formatMillisWithFixedFormat(time); } private final static Comparator<SyncOperation> sOpDumpComparator = (op1, op2) -> { @@ -2561,9 +2559,7 @@ public class SyncManager { accountKey = "Unknown"; } final long elapsedTime = item.elapsedTime; - final Time time = new Time(); final long eventTime = item.eventTime; - time.set(eventTime); final String key = authorityName + "/" + accountKey; final Long lastEventTime = lastTimeMap.get(key); @@ -2628,9 +2624,7 @@ public class SyncManager { authorityName = "Unknown"; accountKey = "Unknown"; } - final Time time = new Time(); final long eventTime = item.eventTime; - time.set(eventTime); pw.printf(" #%-3d: %s %8s ", i + 1, diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java index 7be1b8a3d371..c46fc20b3cc8 100644 --- a/services/core/java/com/android/server/display/ColorFade.java +++ b/services/core/java/com/android/server/display/ColorFade.java @@ -29,6 +29,7 @@ import android.opengl.GLES11Ext; import android.opengl.GLES20; import android.os.IBinder; import android.util.Slog; +import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; import android.view.Surface.OutOfResourcesException; @@ -72,6 +73,9 @@ final class ColorFade { // See code for details. private static final int DEJANK_FRAMES = 3; + private static final int EGL_GL_COLORSPACE_KHR = 0x309D; + private static final int EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT = 0x3490; + private final int mDisplayId; // Set to true when the animation context has been fully prepared. @@ -93,6 +97,7 @@ final class ColorFade { private EGLSurface mEglSurface; private boolean mSurfaceVisible; private float mSurfaceAlpha; + private boolean mIsWideColor; // Texture names. We only use one texture, which contains the screenshot. private final int[] mTexNames = new int[1]; @@ -482,6 +487,8 @@ final class ColorFade { return false; } + mIsWideColor = SurfaceControl.getActiveColorMode(token) + == Display.COLOR_MODE_DISPLAY_P3; SurfaceControl.screenshot(token, s); st.updateTexImage(); st.getTransformMatrix(mTexMatrix); @@ -608,8 +615,16 @@ final class ColorFade { private boolean createEglSurface() { if (mEglSurface == null) { int[] eglSurfaceAttribList = new int[] { + EGL14.EGL_NONE, + EGL14.EGL_NONE, EGL14.EGL_NONE }; + + // If the current display is in wide color, then so is the screenshot. + if (mIsWideColor) { + eglSurfaceAttribList[0] = EGL_GL_COLORSPACE_KHR; + eglSurfaceAttribList[1] = EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT; + } // turn our SurfaceControl into a Surface mEglSurface = EGL14.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, eglSurfaceAttribList, 0); diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index d73c25336808..6f2b33453891 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -28,7 +28,7 @@ import android.net.Network; import android.net.Uri; import android.os.RemoteException; import android.os.UserHandle; -import android.text.format.Time; +import android.text.format.TimeMigrationUtils; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; @@ -1660,17 +1660,13 @@ public final class JobStatus { if (numFailures != 0) { pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures); } - final Time t = new Time(); - final String format = "%Y-%m-%d %H:%M:%S"; if (mLastSuccessfulRunTime != 0) { pw.print(prefix); pw.print("Last successful run: "); - t.set(mLastSuccessfulRunTime); - pw.println(t.format(format)); + pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastSuccessfulRunTime)); } if (mLastFailedRunTime != 0) { pw.print(prefix); pw.print("Last failed run: "); - t.set(mLastFailedRunTime); - pw.println(t.format(format)); + pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastFailedRunTime)); } } diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 6911b7c8f565..461f19bf8b08 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -1608,13 +1608,11 @@ public class GnssLocationProvider extends AbstractLocationProvider implements if (DEBUG) Log.d(TAG, "reportGnssServiceDied"); mHandler.post(() -> { setupNativeGnssService(/* reinitializeGnssServiceHandle = */ true); + // resend configuration into the restarted HAL service. + reloadGpsProperties(); if (isGpsEnabled()) { setGpsEnabled(false); - updateEnabled(); - - // resend configuration into the restarted HAL service. - reloadGpsProperties(); } }); } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 433ce811c8d7..9510db09aa25 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -446,7 +446,7 @@ public class LockSettingsService extends ILockSettings.Stub { public boolean hasEnrolledBiometrics(int userId) { BiometricManager bm = mContext.getSystemService(BiometricManager.class); - return bm.canAuthenticate(userId) == BiometricManager.BIOMETRIC_SUCCESS; + return bm.hasEnrolledBiometrics(userId); } public int binderGetCallingUid() { diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java index f0e431ee0354..84ae7c790a74 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java @@ -48,6 +48,8 @@ import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -390,6 +392,17 @@ class LockSettingsStorage { return stored; } + private void fsyncDirectory(File directory) { + try { + try (FileChannel file = FileChannel.open(directory.toPath(), + StandardOpenOption.READ)) { + file.force(true); + } + } catch (IOException e) { + Slog.e(TAG, "Error syncing directory: " + directory, e); + } + } + private void writeFile(String name, byte[] hash) { synchronized (mFileWriteLock) { RandomAccessFile raf = null; @@ -406,6 +419,7 @@ class LockSettingsStorage { raf.write(hash, 0, hash.length); } raf.close(); + fsyncDirectory((new File(name)).getAbsoluteFile().getParentFile()); } catch (IOException e) { Slog.e(TAG, "Error writing to file " + e); } finally { diff --git a/services/core/java/com/android/server/locksettings/TEST_MAPPING b/services/core/java/com/android/server/locksettings/TEST_MAPPING new file mode 100644 index 000000000000..c1cba5f7f22d --- /dev/null +++ b/services/core/java/com/android/server/locksettings/TEST_MAPPING @@ -0,0 +1,15 @@ +{ + "presubmit": [ + { + "name": "CtsDevicePolicyManagerTestCases", + "options": [ + { + "include-annotation": "com.android.cts.devicepolicy.annotations.LockSettingsTest" + }, + { + "exclude-annotation": "android.platform.test.annotations.FlakyTest" + } + ] + } + ] +} diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java index c54bfc01e031..0ad6c2a69556 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java @@ -19,6 +19,7 @@ package com.android.server.locksettings.recoverablekeystore; import android.app.KeyguardManager; import android.content.Context; import android.os.RemoteException; +import android.os.UserHandle; import android.security.GateKeeper; import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyPermanentlyInvalidatedException; @@ -437,25 +438,31 @@ public class PlatformKeyManager { // so it may live in memory for some time. SecretKey secretKey = generateAesKey(); - long secureUserId = getGateKeeperService().getSecureUserId(userId); - // TODO(b/124095438): Propagate this failure instead of silently failing. - if (secureUserId == GateKeeper.INVALID_SECURE_USER_ID) { - Log.e(TAG, "No SID available for user " + userId); - return; - } - - // Store decryption key first since it is more likely to fail. - mKeyStore.setEntry( - decryptAlias, - new KeyStore.SecretKeyEntry(secretKey), + KeyProtection.Builder decryptionKeyProtection = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT) .setUserAuthenticationRequired(true) .setUserAuthenticationValidityDurationSeconds( USER_AUTHENTICATION_VALIDITY_DURATION_SECONDS) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) - .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE); + if (userId != UserHandle.USER_SYSTEM) { + // Bind decryption key to secondary profile lock screen secret. + long secureUserId = getGateKeeperService().getSecureUserId(userId); + // TODO(b/124095438): Propagate this failure instead of silently failing. + if (secureUserId == GateKeeper.INVALID_SECURE_USER_ID) { + Log.e(TAG, "No SID available for user " + userId); + return; + } + decryptionKeyProtection .setBoundToSpecificSecureUserId(secureUserId) - .build()); + // Ignore caller uid which always belongs to the primary profile. + .setCriticalToDeviceEncryption(true); + } + // Store decryption key first since it is more likely to fail. + mKeyStore.setEntry( + decryptAlias, + new KeyStore.SecretKeyEntry(secretKey), + decryptionKeyProtection.build()); mKeyStore.setEntry( encryptAlias, new KeyStore.SecretKeyEntry(secretKey), diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 4a6eb276bd02..4828bbfff676 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -196,18 +196,20 @@ abstract public class ManagedServices { public void dump(PrintWriter pw, DumpFilter filter) { pw.println(" Allowed " + getCaption() + "s:"); - final int N = mApproved.size(); - for (int i = 0 ; i < N; i++) { - final int userId = mApproved.keyAt(i); - final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); - if (approvedByType != null) { - final int M = approvedByType.size(); - for (int j = 0; j < M; j++) { - final boolean isPrimary = approvedByType.keyAt(j); - final ArraySet<String> approved = approvedByType.valueAt(j); - if (approvedByType != null && approvedByType.size() > 0) { - pw.println(" " + String.join(ENABLED_SERVICES_SEPARATOR, approved) - + " (user: " + userId + " isPrimary: " + isPrimary + ")"); + synchronized (mApproved) { + final int N = mApproved.size(); + for (int i = 0; i < N; i++) { + final int userId = mApproved.keyAt(i); + final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); + if (approvedByType != null) { + final int M = approvedByType.size(); + for (int j = 0; j < M; j++) { + final boolean isPrimary = approvedByType.keyAt(j); + final ArraySet<String> approved = approvedByType.valueAt(j); + if (approvedByType != null && approvedByType.size() > 0) { + pw.println(" " + String.join(ENABLED_SERVICES_SEPARATOR, approved) + + " (user: " + userId + " isPrimary: " + isPrimary + ")"); + } } } } @@ -240,23 +242,25 @@ abstract public class ManagedServices { public void dump(ProtoOutputStream proto, DumpFilter filter) { proto.write(ManagedServicesProto.CAPTION, getCaption()); - final int N = mApproved.size(); - for (int i = 0 ; i < N; i++) { - final int userId = mApproved.keyAt(i); - final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); - if (approvedByType != null) { - final int M = approvedByType.size(); - for (int j = 0; j < M; j++) { - final boolean isPrimary = approvedByType.keyAt(j); - final ArraySet<String> approved = approvedByType.valueAt(j); - if (approvedByType != null && approvedByType.size() > 0) { - final long sToken = proto.start(ManagedServicesProto.APPROVED); - for (String s : approved) { - proto.write(ServiceProto.NAME, s); + synchronized (mApproved) { + final int N = mApproved.size(); + for (int i = 0; i < N; i++) { + final int userId = mApproved.keyAt(i); + final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); + if (approvedByType != null) { + final int M = approvedByType.size(); + for (int j = 0; j < M; j++) { + final boolean isPrimary = approvedByType.keyAt(j); + final ArraySet<String> approved = approvedByType.valueAt(j); + if (approvedByType != null && approvedByType.size() > 0) { + final long sToken = proto.start(ManagedServicesProto.APPROVED); + for (String s : approved) { + proto.write(ServiceProto.NAME, s); + } + proto.write(ServiceProto.USER_ID, userId); + proto.write(ServiceProto.IS_PRIMARY, isPrimary); + proto.end(sToken); } - proto.write(ServiceProto.USER_ID, userId); - proto.write(ServiceProto.IS_PRIMARY, isPrimary); - proto.end(sToken); } } } @@ -315,33 +319,36 @@ abstract public class ManagedServices { trimApprovedListsAccordingToInstalledServices(userId); } - final int N = mApproved.size(); - for (int i = 0 ; i < N; i++) { - final int approvedUserId = mApproved.keyAt(i); - if (forBackup && approvedUserId != userId) { - continue; - } - final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); - if (approvedByType != null) { - final int M = approvedByType.size(); - for (int j = 0; j < M; j++) { - final boolean isPrimary = approvedByType.keyAt(j); - final Set<String> approved = approvedByType.valueAt(j); - if (approved != null) { - String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved); - out.startTag(null, TAG_MANAGED_SERVICES); - out.attribute(null, ATT_APPROVED_LIST, allowedItems); - out.attribute(null, ATT_USER_ID, Integer.toString(approvedUserId)); - out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary)); - writeExtraAttributes(out, approvedUserId); - out.endTag(null, TAG_MANAGED_SERVICES); - - if (!forBackup && isPrimary) { - // Also write values to settings, for observers who haven't migrated yet - Settings.Secure.putStringForUser(mContext.getContentResolver(), - getConfig().secureSettingName, allowedItems, approvedUserId); - } + synchronized (mApproved) { + final int N = mApproved.size(); + for (int i = 0; i < N; i++) { + final int approvedUserId = mApproved.keyAt(i); + if (forBackup && approvedUserId != userId) { + continue; + } + final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); + if (approvedByType != null) { + final int M = approvedByType.size(); + for (int j = 0; j < M; j++) { + final boolean isPrimary = approvedByType.keyAt(j); + final Set<String> approved = approvedByType.valueAt(j); + if (approved != null) { + String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved); + out.startTag(null, TAG_MANAGED_SERVICES); + out.attribute(null, ATT_APPROVED_LIST, allowedItems); + out.attribute(null, ATT_USER_ID, Integer.toString(approvedUserId)); + out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary)); + writeExtraAttributes(out, approvedUserId); + out.endTag(null, TAG_MANAGED_SERVICES); + + if (!forBackup && isPrimary) { + // Also write values to settings, for observers who haven't migrated yet + Settings.Secure.putStringForUser(mContext.getContentResolver(), + getConfig().secureSettingName, allowedItems, + approvedUserId); + } + } } } } @@ -440,23 +447,25 @@ abstract public class ManagedServices { if (TextUtils.isEmpty(approved)) { approved = ""; } - ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); - if (approvedByType == null) { - approvedByType = new ArrayMap<>(); - mApproved.put(userId, approvedByType); - } + synchronized (mApproved) { + ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); + if (approvedByType == null) { + approvedByType = new ArrayMap<>(); + mApproved.put(userId, approvedByType); + } - ArraySet<String> approvedList = approvedByType.get(isPrimary); - if (approvedList == null) { - approvedList = new ArraySet<>(); - approvedByType.put(isPrimary, approvedList); - } + ArraySet<String> approvedList = approvedByType.get(isPrimary); + if (approvedList == null) { + approvedList = new ArraySet<>(); + approvedByType.put(isPrimary, approvedList); + } - String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR); - for (String pkgOrComponent : approvedArray) { - String approvedItem = getApprovedValue(pkgOrComponent); - if (approvedItem != null) { - approvedList.add(approvedItem); + String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR); + for (String pkgOrComponent : approvedArray) { + String approvedItem = getApprovedValue(pkgOrComponent); + if (approvedItem != null) { + approvedList.add(approvedItem); + } } } } @@ -469,23 +478,25 @@ abstract public class ManagedServices { boolean isPrimary, boolean enabled) { Slog.i(TAG, (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " " + pkgOrComponent); - ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId); - if (allowedByType == null) { - allowedByType = new ArrayMap<>(); - mApproved.put(userId, allowedByType); - } - ArraySet<String> approved = allowedByType.get(isPrimary); - if (approved == null) { - approved = new ArraySet<>(); - allowedByType.put(isPrimary, approved); - } - String approvedItem = getApprovedValue(pkgOrComponent); - - if (approvedItem != null) { - if (enabled) { - approved.add(approvedItem); - } else { - approved.remove(approvedItem); + synchronized (mApproved) { + ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId); + if (allowedByType == null) { + allowedByType = new ArrayMap<>(); + mApproved.put(userId, allowedByType); + } + ArraySet<String> approved = allowedByType.get(isPrimary); + if (approved == null) { + approved = new ArraySet<>(); + allowedByType.put(isPrimary, approved); + } + String approvedItem = getApprovedValue(pkgOrComponent); + + if (approvedItem != null) { + if (enabled) { + approved.add(approvedItem); + } else { + approved.remove(approvedItem); + } } } @@ -504,22 +515,26 @@ abstract public class ManagedServices { } protected String getApproved(int userId, boolean primary) { - final ArrayMap<Boolean, ArraySet<String>> allowedByType = - mApproved.getOrDefault(userId, new ArrayMap<>()); - ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>()); - return String.join(ENABLED_SERVICES_SEPARATOR, approved); + synchronized (mApproved) { + final ArrayMap<Boolean, ArraySet<String>> allowedByType = + mApproved.getOrDefault(userId, new ArrayMap<>()); + ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>()); + return String.join(ENABLED_SERVICES_SEPARATOR, approved); + } } protected List<ComponentName> getAllowedComponents(int userId) { final List<ComponentName> allowedComponents = new ArrayList<>(); - final ArrayMap<Boolean, ArraySet<String>> allowedByType = - mApproved.getOrDefault(userId, new ArrayMap<>()); - for (int i = 0; i < allowedByType.size(); i++) { - final ArraySet<String> allowed = allowedByType.valueAt(i); - for (int j = 0; j < allowed.size(); j++) { - ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j)); - if (cn != null) { - allowedComponents.add(cn); + synchronized (mApproved) { + final ArrayMap<Boolean, ArraySet<String>> allowedByType = + mApproved.getOrDefault(userId, new ArrayMap<>()); + for (int i = 0; i < allowedByType.size(); i++) { + final ArraySet<String> allowed = allowedByType.valueAt(i); + for (int j = 0; j < allowed.size(); j++) { + ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j)); + if (cn != null) { + allowedComponents.add(cn); + } } } } @@ -528,14 +543,16 @@ abstract public class ManagedServices { protected List<String> getAllowedPackages(int userId) { final List<String> allowedPackages = new ArrayList<>(); - final ArrayMap<Boolean, ArraySet<String>> allowedByType = - mApproved.getOrDefault(userId, new ArrayMap<>()); - for (int i = 0; i < allowedByType.size(); i++) { - final ArraySet<String> allowed = allowedByType.valueAt(i); - for (int j = 0; j < allowed.size(); j++) { - String pkgName = getPackageName(allowed.valueAt(j)); - if (!TextUtils.isEmpty(pkgName)) { - allowedPackages.add(pkgName); + synchronized (mApproved) { + final ArrayMap<Boolean, ArraySet<String>> allowedByType = + mApproved.getOrDefault(userId, new ArrayMap<>()); + for (int i = 0; i < allowedByType.size(); i++) { + final ArraySet<String> allowed = allowedByType.valueAt(i); + for (int j = 0; j < allowed.size(); j++) { + String pkgName = getPackageName(allowed.valueAt(j)); + if (!TextUtils.isEmpty(pkgName)) { + allowedPackages.add(pkgName); + } } } } @@ -543,12 +560,14 @@ abstract public class ManagedServices { } protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) { - ArrayMap<Boolean, ArraySet<String>> allowedByType = - mApproved.getOrDefault(userId, new ArrayMap<>()); - for (int i = 0; i < allowedByType.size(); i++) { - ArraySet<String> allowed = allowedByType.valueAt(i); - if (allowed.contains(pkgOrComponent)) { - return true; + synchronized (mApproved) { + ArrayMap<Boolean, ArraySet<String>> allowedByType = + mApproved.getOrDefault(userId, new ArrayMap<>()); + for (int i = 0; i < allowedByType.size(); i++) { + ArraySet<String> allowed = allowedByType.valueAt(i); + if (allowed.contains(pkgOrComponent)) { + return true; + } } } return false; @@ -558,19 +577,21 @@ abstract public class ManagedServices { if (pkg == null) { return false; } - ArrayMap<Boolean, ArraySet<String>> allowedByType = - mApproved.getOrDefault(userId, new ArrayMap<>()); - for (int i = 0; i < allowedByType.size(); i++) { - ArraySet<String> allowed = allowedByType.valueAt(i); - for (String allowedEntry : allowed) { - ComponentName component = ComponentName.unflattenFromString(allowedEntry); - if (component != null) { - if (pkg.equals(component.getPackageName())) { - return true; - } - } else { - if (pkg.equals(allowedEntry)) { - return true; + synchronized (mApproved) { + ArrayMap<Boolean, ArraySet<String>> allowedByType = + mApproved.getOrDefault(userId, new ArrayMap<>()); + for (int i = 0; i < allowedByType.size(); i++) { + ArraySet<String> allowed = allowedByType.valueAt(i); + for (String allowedEntry : allowed) { + ComponentName component = ComponentName.unflattenFromString(allowedEntry); + if (component != null) { + if (pkg.equals(component.getPackageName())) { + return true; + } + } else { + if (pkg.equals(allowedEntry)) { + return true; + } } } } @@ -616,7 +637,9 @@ abstract public class ManagedServices { public void onUserRemoved(int user) { Slog.i(TAG, "Removing approved services for removed user " + user); - mApproved.remove(user); + synchronized (mApproved) { + mApproved.remove(user); + } rebindServices(true, user); } @@ -797,14 +820,16 @@ abstract public class ManagedServices { protected Set<String> getAllowedPackages() { final Set<String> allowedPackages = new ArraySet<>(); - for (int k = 0; k < mApproved.size(); k++) { - ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k); - for (int i = 0; i < allowedByType.size(); i++) { - final ArraySet<String> allowed = allowedByType.valueAt(i); - for (int j = 0; j < allowed.size(); j++) { - String pkgName = getPackageName(allowed.valueAt(j)); - if (!TextUtils.isEmpty(pkgName)) { - allowedPackages.add(pkgName); + synchronized (mApproved) { + for (int k = 0; k < mApproved.size(); k++) { + ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k); + for (int i = 0; i < allowedByType.size(); i++) { + final ArraySet<String> allowed = allowedByType.valueAt(i); + for (int j = 0; j < allowed.size(); j++) { + String pkgName = getPackageName(allowed.valueAt(j)); + if (!TextUtils.isEmpty(pkgName)) { + allowedPackages.add(pkgName); + } } } } @@ -813,22 +838,24 @@ abstract public class ManagedServices { } private void trimApprovedListsAccordingToInstalledServices(int userId) { - final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); - if (approvedByType == null) { - return; - } - for (int i = 0; i < approvedByType.size(); i++) { - final ArraySet<String> approved = approvedByType.valueAt(i); - for (int j = approved.size() - 1; j >= 0; j--) { - final String approvedPackageOrComponent = approved.valueAt(j); - if (!isValidEntry(approvedPackageOrComponent, userId)){ - approved.removeAt(j); - Slog.v(TAG, "Removing " + approvedPackageOrComponent - + " from approved list; no matching services found"); - } else { - if (DEBUG) { - Slog.v(TAG, "Keeping " + approvedPackageOrComponent - + " on approved list; matching services found"); + synchronized (mApproved) { + final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); + if (approvedByType == null) { + return; + } + for (int i = 0; i < approvedByType.size(); i++) { + final ArraySet<String> approved = approvedByType.valueAt(i); + for (int j = approved.size() - 1; j >= 0; j--) { + final String approvedPackageOrComponent = approved.valueAt(j); + if (!isValidEntry(approvedPackageOrComponent, userId)) { + approved.removeAt(j); + Slog.v(TAG, "Removing " + approvedPackageOrComponent + + " from approved list; no matching services found"); + } else { + if (DEBUG) { + Slog.v(TAG, "Keeping " + approvedPackageOrComponent + + " on approved list; matching services found"); + } } } } @@ -837,20 +864,23 @@ abstract public class ManagedServices { private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg) { boolean removed = false; - final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(uninstalledUserId); - if (approvedByType != null) { - int M = approvedByType.size(); - for (int j = 0; j < M; j++) { - final ArraySet<String> approved = approvedByType.valueAt(j); - int O = approved.size(); - for (int k = O - 1; k >= 0; k--) { - final String packageOrComponent = approved.valueAt(k); - final String packageName = getPackageName(packageOrComponent); - if (TextUtils.equals(pkg, packageName)) { - approved.removeAt(k); - if (DEBUG) { - Slog.v(TAG, "Removing " + packageOrComponent - + " from approved list; uninstalled"); + synchronized (mApproved) { + final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get( + uninstalledUserId); + if (approvedByType != null) { + int M = approvedByType.size(); + for (int j = 0; j < M; j++) { + final ArraySet<String> approved = approvedByType.valueAt(j); + int O = approved.size(); + for (int k = O - 1; k >= 0; k--) { + final String packageOrComponent = approved.valueAt(k); + final String packageName = getPackageName(packageOrComponent); + if (TextUtils.equals(pkg, packageName)) { + approved.removeAt(k); + if (DEBUG) { + Slog.v(TAG, "Removing " + packageOrComponent + + " from approved list; uninstalled"); + } } } } @@ -887,17 +917,19 @@ abstract public class ManagedServices { for (int i = 0; i < nUserIds; ++i) { final int userId = userIds.get(i); - final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userId); - if (approvedLists != null) { - final int N = approvedLists.size(); - for (int j = 0; j < N; j++) { - ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId); - if (approvedByUser == null) { - approvedByUser = new ArraySet<>(); - componentsByUser.put(userId, approvedByUser); + synchronized (mApproved) { + final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userId); + if (approvedLists != null) { + final int N = approvedLists.size(); + for (int j = 0; j < N; j++) { + ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId); + if (approvedByUser == null) { + approvedByUser = new ArraySet<>(); + componentsByUser.put(userId, approvedByUser); + } + approvedByUser.addAll( + loadComponentNamesFromValues(approvedLists.valueAt(j), userId)); } - approvedByUser.addAll( - loadComponentNamesFromValues(approvedLists.valueAt(j), userId)); } } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index d30895efbdc3..20dbe0138acc 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -473,6 +473,8 @@ public class NotificationManagerService extends SystemService { private MetricsLogger mMetricsLogger; private TriPredicate<String, Integer, String> mAllowedManagedServicePackages; + private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable(); + private static class Archive { final int mBufferSize; final ArrayDeque<StatusBarNotification> mBuffer; @@ -666,7 +668,14 @@ public class NotificationManagerService extends SystemService { @VisibleForTesting protected void handleSavePolicyFile() { - IoThread.getHandler().post(() -> { + if (!IoThread.getHandler().hasCallbacks(mSavePolicyFile)) { + IoThread.getHandler().post(mSavePolicyFile); + } + } + + private final class SavePolicyFileRunnable implements Runnable { + @Override + public void run() { if (DBG) Slog.d(TAG, "handleSavePolicyFile"); synchronized (mPolicyFile) { final FileOutputStream stream; @@ -686,7 +695,7 @@ public class NotificationManagerService extends SystemService { } } BackupManager.dataChanged(getContext().getPackageName()); - }); + } } private void writePolicyXml(OutputStream stream, boolean forBackup, int userId) diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 6f28675d051b..934511bf88d1 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -296,22 +296,12 @@ final class OverlayManagerServiceImpl { */ private void updateAndRefreshOverlaysForTarget(@NonNull final String targetPackageName, final int userId, final int flags) { - final List<OverlayInfo> ois = new ArrayList<>(); - - // Framework overlays added first because order matters when resolving a resource - if (!"android".equals(targetPackageName)) { - ois.addAll(mSettings.getOverlaysForTarget("android", userId)); - } - - // Then add the targeted, non-framework overlays which have higher priority - ois.addAll(mSettings.getOverlaysForTarget(targetPackageName, userId)); - - final List<String> enabledBaseCodePaths = new ArrayList<>(ois.size()); + final List<OverlayInfo> targetOverlays = mSettings.getOverlaysForTarget(targetPackageName, + userId); + // Update the state for any overlay that targets this package. boolean modified = false; - final int n = ois.size(); - for (int i = 0; i < n; i++) { - final OverlayInfo oi = ois.get(i); + for (final OverlayInfo oi : targetOverlays) { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName, userId); if (overlayPackage == null) { @@ -324,25 +314,39 @@ final class OverlayManagerServiceImpl { Slog.e(TAG, "failed to update settings", e); modified |= mSettings.remove(oi.packageName, userId); } - - if (oi.isEnabled() && overlayPackage.applicationInfo != null) { - enabledBaseCodePaths.add(overlayPackage.applicationInfo.getBaseCodePath()); - } } } if (!modified) { + // Update the overlay paths of the target within package manager if necessary. + final List<String> enabledOverlayPaths = new ArrayList<>(targetOverlays.size()); + + // Framework overlays are first in the overlay paths of a package within PackageManager. + for (final OverlayInfo oi : mSettings.getOverlaysForTarget("android", userId)) { + if (oi.isEnabled()) { + enabledOverlayPaths.add(oi.baseCodePath); + } + } + + for (final OverlayInfo oi : targetOverlays) { + if (oi.isEnabled()) { + enabledOverlayPaths.add(oi.baseCodePath); + } + } + + // TODO(): Use getEnabledOverlayPaths(userId, targetPackageName) instead of + // resourceDirs if in the future resourceDirs contains APKs other than overlays PackageInfo packageInfo = mPackageManager.getPackageInfo(targetPackageName, userId); ApplicationInfo appInfo = packageInfo == null ? null : packageInfo.applicationInfo; String[] resourceDirs = appInfo == null ? null : appInfo.resourceDirs; // If the lists aren't the same length, the enabled overlays have changed - if (ArrayUtils.size(resourceDirs) != enabledBaseCodePaths.size()) { + if (ArrayUtils.size(resourceDirs) != enabledOverlayPaths.size()) { modified = true; } else if (resourceDirs != null) { // If any element isn't equal, an overlay or the order of overlays has changed for (int index = 0; index < resourceDirs.length; index++) { - if (!resourceDirs[index].equals(enabledBaseCodePaths.get(index))) { + if (!resourceDirs[index].equals(enabledOverlayPaths.get(index))) { modified = true; break; } diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java index 8b9af7a435e4..8f38026b365f 100644 --- a/services/core/java/com/android/server/pm/InstantAppRegistry.java +++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java @@ -112,7 +112,7 @@ class InstantAppRegistry { private final CookiePersistence mCookiePersistence; /** State for uninstalled instant apps */ - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private SparseArray<List<UninstalledInstantAppState>> mUninstalledInstantApps; /** @@ -121,11 +121,11 @@ class InstantAppRegistry { * The value is a set of instant app UIDs. * UserID -> TargetAppId -> InstantAppId */ - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private SparseArray<SparseArray<SparseBooleanArray>> mInstantGrants; /** The set of all installed instant apps. UserID -> AppID */ - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private SparseArray<SparseBooleanArray> mInstalledInstantAppUids; public InstantAppRegistry(PackageManagerService service) { @@ -133,7 +133,7 @@ class InstantAppRegistry { mCookiePersistence = new CookiePersistence(BackgroundThread.getHandler().getLooper()); } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public byte[] getInstantAppCookieLPw(@NonNull String packageName, @UserIdInt int userId) { // Only installed packages can get their own cookie @@ -157,7 +157,7 @@ class InstantAppRegistry { return null; } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public boolean setInstantAppCookieLPw(@NonNull String packageName, @Nullable byte[] cookie, @UserIdInt int userId) { if (cookie != null && cookie.length > 0) { @@ -182,7 +182,7 @@ class InstantAppRegistry { private void persistInstantApplicationCookie(@Nullable byte[] cookie, @NonNull String packageName, @NonNull File cookieFile, @UserIdInt int userId) { - synchronized (mService.mPackages) { + synchronized (mService.mLock) { File appDir = getInstantApplicationDir(packageName, userId); if (!appDir.exists() && !appDir.mkdirs()) { Slog.e(LOG_TAG, "Cannot create instant app cookie directory"); @@ -250,7 +250,7 @@ class InstantAppRegistry { } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public @Nullable List<InstantAppInfo> getInstantAppsLPr(@UserIdInt int userId) { List<InstantAppInfo> installedApps = getInstalledInstantApplicationsLPr(userId); List<InstantAppInfo> uninstalledApps = getUninstalledInstantApplicationsLPr(userId); @@ -263,7 +263,7 @@ class InstantAppRegistry { return uninstalledApps; } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public void onPackageInstalledLPw(@NonNull PackageParser.Package pkg, @NonNull int[] userIds) { PackageSetting ps = (PackageSetting) pkg.mExtras; if (ps == null) { @@ -334,7 +334,7 @@ class InstantAppRegistry { } } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public void onPackageUninstalledLPw(@NonNull PackageParser.Package pkg, @NonNull int[] userIds) { PackageSetting ps = (PackageSetting) pkg.mExtras; @@ -360,7 +360,7 @@ class InstantAppRegistry { } } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public void onUserRemovedLPw(int userId) { if (mUninstalledInstantApps != null) { mUninstalledInstantApps.remove(userId); @@ -399,7 +399,7 @@ class InstantAppRegistry { return instantGrantList.get(instantAppId); } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public void grantInstantAccessLPw(@UserIdInt int userId, @Nullable Intent intent, int targetAppId, int instantAppId) { if (mInstalledInstantAppUids == null) { @@ -434,7 +434,7 @@ class InstantAppRegistry { instantGrantList.put(instantAppId, true /*granted*/); } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public void addInstantAppLPw(@UserIdInt int userId, int instantAppId) { if (mInstalledInstantAppUids == null) { mInstalledInstantAppUids = new SparseArray<>(); @@ -447,7 +447,7 @@ class InstantAppRegistry { instantAppList.put(instantAppId, true /*installed*/); } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private void removeInstantAppLPw(@UserIdInt int userId, int instantAppId) { // remove from the installed list if (mInstalledInstantAppUids == null) { @@ -473,7 +473,7 @@ class InstantAppRegistry { } } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private void removeAppLPw(@UserIdInt int userId, int targetAppId) { // remove from the installed list if (mInstantGrants == null) { @@ -486,7 +486,7 @@ class InstantAppRegistry { targetAppList.delete(targetAppId); } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private void addUninstalledInstantAppLPw(@NonNull PackageParser.Package pkg, @UserIdInt int userId) { InstantAppInfo uninstalledApp = createInstantAppInfoForPackage( @@ -541,13 +541,13 @@ class InstantAppRegistry { } } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") boolean hasInstantApplicationMetadataLPr(String packageName, int userId) { return hasUninstalledInstantAppStateLPr(packageName, userId) || hasInstantAppMetadataLPr(packageName, userId); } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") public void deleteInstantApplicationMetadataLPw(@NonNull String packageName, @UserIdInt int userId) { removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> @@ -564,7 +564,7 @@ class InstantAppRegistry { } } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private void removeUninstalledInstantAppStateLPw( @NonNull Predicate<UninstalledInstantAppState> criteria, @UserIdInt int userId) { if (mUninstalledInstantApps == null) { @@ -592,7 +592,7 @@ class InstantAppRegistry { } } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private boolean hasUninstalledInstantAppStateLPr(String packageName, @UserIdInt int userId) { if (mUninstalledInstantApps == null) { return false; @@ -685,7 +685,7 @@ class InstantAppRegistry { final long now = System.currentTimeMillis(); // Prune first installed instant apps - synchronized (mService.mPackages) { + synchronized (mService.mLock) { allUsers = PackageManagerService.sUserManager.getUserIds(); final int packageCount = mService.mPackages.size(); @@ -768,7 +768,7 @@ class InstantAppRegistry { } // Prune uninstalled instant apps - synchronized (mService.mPackages) { + synchronized (mService.mLock) { // TODO: Track last used time for uninstalled instant apps for better pruning for (int userId : UserManagerService.getInstance().getUserIds()) { // Prune in-memory state @@ -811,7 +811,7 @@ class InstantAppRegistry { return false; } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private @Nullable List<InstantAppInfo> getInstalledInstantApplicationsLPr( @UserIdInt int userId) { List<InstantAppInfo> result = null; @@ -866,7 +866,7 @@ class InstantAppRegistry { } } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private @Nullable List<InstantAppInfo> getUninstalledInstantApplicationsLPr( @UserIdInt int userId) { List<UninstalledInstantAppState> uninstalledAppStates = @@ -939,7 +939,7 @@ class InstantAppRegistry { return uninstalledAppState.mInstantAppInfo; } - @GuardedBy("mService.mPackages") + @GuardedBy("mService.mLock") private @Nullable List<UninstalledInstantAppState> getUninstalledInstantAppStatesLPr( @UserIdInt int userId) { List<UninstalledInstantAppState> uninstalledAppStates = null; diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index e5a2e777a796..d49ecdda679d 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -120,7 +120,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { } final List<PackageParser.Package> important; final List<PackageParser.Package> others; - synchronized (mPackageManagerService.mPackages) { + synchronized (mPackageManagerService.mLock) { // Important: the packages we need to run with ab-ota compiler-reason. important = PackageManagerServiceUtils.getPackagesForDexopt( mPackageManagerService.mPackages.values(), mPackageManagerService, diff --git a/services/core/java/com/android/server/pm/PackageAbiHelper.java b/services/core/java/com/android/server/pm/PackageAbiHelper.java new file mode 100644 index 000000000000..da4558277b95 --- /dev/null +++ b/services/core/java/com/android/server/pm/PackageAbiHelper.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.annotation.Nullable; +import android.content.pm.PackageParser; + +import com.android.internal.annotations.VisibleForTesting; + +import java.io.File; +import java.util.List; +import java.util.Set; + +@VisibleForTesting +interface PackageAbiHelper { + /** + * Derive and set the location of native libraries for the given package, + * which varies depending on where and how the package was installed. + * + * WARNING: This API enables modifying of the package. + * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary + */ + void setNativeLibraryPaths(PackageParser.Package pkg, File appLib32InstallDir); + + /** + * Calculate the abis and roots for a bundled app. These can uniquely + * be determined from the contents of the system partition, i.e whether + * it contains 64 or 32 bit shared libraries etc. We do not validate any + * of this information, and instead assume that the system was built + * sensibly. + * + * WARNING: This API enables modifying of the package. + * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary + */ + void setBundledAppAbisAndRoots(PackageParser.Package pkg, + PackageSetting pkgSetting); + + /** + * Derive the ABI of a non-system package located at {@code scanFile}. This information + * is derived purely on the basis of the contents of {@code scanFile} and + * {@code cpuAbiOverride}. + * + * If {@code extractLibs} is true, native libraries are extracted from the app if required. + * + * WARNING: This API enables modifying of the package. + * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary + */ + void derivePackageAbi(PackageParser.Package pkg, String cpuAbiOverride, + boolean extractLibs) + throws PackageManagerException; + + /** + * Adjusts ABIs for a set of packages belonging to a shared user so that they all match. + * i.e, so that all packages can be run inside a single process if required. + * + * Optionally, callers can pass in a parsed package via {@code newPackage} in which case + * this function will either try and make the ABI for all packages in + * {@code packagesForUser} match {@code scannedPackage} or will update the ABI of + * {@code scannedPackage} to match the ABI selected for {@code packagesForUser}. This + * variant is used when installing or updating a package that belongs to a shared user. + * + * NOTE: We currently only match for the primary CPU abi string. Matching the secondary + * adds unnecessary complexity. + * + * WARNING: This API enables modifying of the package. + * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary + */ + @Nullable + List<String> adjustCpuAbisForSharedUser( + Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage); +} diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java new file mode 100644 index 000000000000..4ecc888cb33c --- /dev/null +++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; +import static android.content.pm.PackageParser.isApkFile; +import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; + +import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME; +import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME; +import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; +import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; + +import android.annotation.Nullable; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.os.Build; +import android.os.Environment; +import android.os.FileUtils; +import android.os.Trace; +import android.text.TextUtils; +import android.util.Slog; + +import com.android.internal.content.NativeLibraryHelper; +import com.android.internal.util.ArrayUtils; + +import dalvik.system.VMRuntime; + +import libcore.io.IoUtils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +final class PackageAbiHelperImpl implements PackageAbiHelper { + + @Override + public void setNativeLibraryPaths(PackageParser.Package pkg, File appLib32InstallDir) { + final ApplicationInfo info = pkg.applicationInfo; + final String codePath = pkg.codePath; + final File codeFile = new File(codePath); + final boolean bundledApp = info.isSystemApp() && !info.isUpdatedSystemApp(); + + info.nativeLibraryRootDir = null; + info.nativeLibraryRootRequiresIsa = false; + info.nativeLibraryDir = null; + info.secondaryNativeLibraryDir = null; + + if (isApkFile(codeFile)) { + // Monolithic install + if (bundledApp) { + // If "/system/lib64/apkname" exists, assume that is the per-package + // native library directory to use; otherwise use "/system/lib/apkname". + final String apkRoot = calculateBundledApkRoot(info.sourceDir); + final boolean is64Bit = VMRuntime.is64BitInstructionSet( + getPrimaryInstructionSet(info)); + + // This is a bundled system app so choose the path based on the ABI. + // if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this + // is just the default path. + final String apkName = deriveCodePathName(codePath); + final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME; + info.nativeLibraryRootDir = Environment.buildPath(new File(apkRoot), libDir, + apkName).getAbsolutePath(); + + if (info.secondaryCpuAbi != null) { + final String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME; + info.secondaryNativeLibraryDir = Environment.buildPath(new File(apkRoot), + secondaryLibDir, apkName).getAbsolutePath(); + } + } else { + final String apkName = deriveCodePathName(codePath); + info.nativeLibraryRootDir = new File(appLib32InstallDir, apkName) + .getAbsolutePath(); + } + + info.nativeLibraryRootRequiresIsa = false; + info.nativeLibraryDir = info.nativeLibraryRootDir; + } else { + // Cluster install + info.nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath(); + info.nativeLibraryRootRequiresIsa = true; + + info.nativeLibraryDir = new File(info.nativeLibraryRootDir, + getPrimaryInstructionSet(info)).getAbsolutePath(); + + if (info.secondaryCpuAbi != null) { + info.secondaryNativeLibraryDir = new File(info.nativeLibraryRootDir, + VMRuntime.getInstructionSet(info.secondaryCpuAbi)).getAbsolutePath(); + } + } + } + + @Override + public void setBundledAppAbisAndRoots(PackageParser.Package pkg, + PackageSetting pkgSetting) { + final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath()); + + // If "/system/lib64/apkname" exists, assume that is the per-package + // native library directory to use; otherwise use "/system/lib/apkname". + final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir); + setBundledAppAbi(pkg, apkRoot, apkName); + // pkgSetting might be null during rescan following uninstall of updates + // to a bundled app, so accommodate that possibility. The settings in + // that case will be established later from the parsed package. + // + // If the settings aren't null, sync them up with what we've just derived. + // note that apkRoot isn't stored in the package settings. + if (pkgSetting != null) { + pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; + pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; + } + } + + /** + * Deduces the ABI of a bundled app and sets the relevant fields on the + * parsed pkg object. + * + * @param apkRoot the root of the installed apk, something like {@code /system} or + * {@code /oem} under which system libraries are installed. + * @param apkName the name of the installed package. + */ + private void setBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) { + final File codeFile = new File(pkg.codePath); + + final boolean has64BitLibs; + final boolean has32BitLibs; + if (isApkFile(codeFile)) { + // Monolithic install + has64BitLibs = + (new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath())).exists(); + has32BitLibs = (new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath())).exists(); + } else { + // Cluster install + final File rootDir = new File(codeFile, LIB_DIR_NAME); + if (!ArrayUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS) + && !TextUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS[0])) { + final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_64_BIT_ABIS[0]); + has64BitLibs = (new File(rootDir, isa)).exists(); + } else { + has64BitLibs = false; + } + if (!ArrayUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS) + && !TextUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS[0])) { + final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_32_BIT_ABIS[0]); + has32BitLibs = (new File(rootDir, isa)).exists(); + } else { + has32BitLibs = false; + } + } + + if (has64BitLibs && !has32BitLibs) { + // The package has 64 bit libs, but not 32 bit libs. Its primary + // ABI should be 64 bit. We can safely assume here that the bundled + // native libraries correspond to the most preferred ABI in the list. + + pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; + pkg.applicationInfo.secondaryCpuAbi = null; + } else if (has32BitLibs && !has64BitLibs) { + // The package has 32 bit libs but not 64 bit libs. Its primary + // ABI should be 32 bit. + + pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; + pkg.applicationInfo.secondaryCpuAbi = null; + } else if (has32BitLibs && has64BitLibs) { + // The application has both 64 and 32 bit bundled libraries. We check + // here that the app declares multiArch support, and warn if it doesn't. + // + // We will be lenient here and record both ABIs. The primary will be the + // ABI that's higher on the list, i.e, a device that's configured to prefer + // 64 bit apps will see a 64 bit primary ABI, + + if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0) { + Slog.e(PackageManagerService.TAG, + "Package " + pkg + " has multiple bundled libs, but is not multiarch."); + } + + if (VMRuntime.is64BitInstructionSet(getPreferredInstructionSet())) { + pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; + pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; + } else { + pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; + pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; + } + } else { + pkg.applicationInfo.primaryCpuAbi = null; + pkg.applicationInfo.secondaryCpuAbi = null; + } + } + + @Override + public void derivePackageAbi(PackageParser.Package pkg, String cpuAbiOverride, + boolean extractLibs) + throws PackageManagerException { + // Give ourselves some initial paths; we'll come back for another + // pass once we've determined ABI below. + setNativeLibraryPaths(pkg, PackageManagerService.sAppLib32InstallDir); + + // We shouldn't attempt to extract libs from system app when it was not updated. + if (PackageManagerService.isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) { + extractLibs = false; + } + + final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir; + final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa; + + NativeLibraryHelper.Handle handle = null; + try { + handle = NativeLibraryHelper.Handle.create(pkg); + // TODO(multiArch): This can be null for apps that didn't go through the + // usual installation process. We can calculate it again, like we + // do during install time. + // + // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally + // unnecessary. + final File nativeLibraryRoot = new File(nativeLibraryRootStr); + + // Null out the abis so that they can be recalculated. + pkg.applicationInfo.primaryCpuAbi = null; + pkg.applicationInfo.secondaryCpuAbi = null; + if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0) { + // Warn if we've set an abiOverride for multi-lib packages.. + // By definition, we need to copy both 32 and 64 bit libraries for + // such packages. + if (pkg.cpuAbiOverride != null + && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) { + Slog.w(PackageManagerService.TAG, + "Ignoring abiOverride for multi arch application."); + } + + int abi32 = PackageManager.NO_NATIVE_LIBRARIES; + int abi64 = PackageManager.NO_NATIVE_LIBRARIES; + if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { + if (extractLibs) { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); + abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, + nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, + useIsaSpecificSubdirs); + } else { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); + abi32 = NativeLibraryHelper.findSupportedAbi( + handle, Build.SUPPORTED_32_BIT_ABIS); + } + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + + // Shared library native code should be in the APK zip aligned + if (abi32 >= 0 && pkg.isLibrary() && extractLibs) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Shared library native lib extraction not supported"); + } + + maybeThrowExceptionForMultiArchCopy( + "Error unpackaging 32 bit native libs for multiarch app.", abi32); + + if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { + if (extractLibs) { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); + abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, + nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, + useIsaSpecificSubdirs); + } else { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); + abi64 = NativeLibraryHelper.findSupportedAbi( + handle, Build.SUPPORTED_64_BIT_ABIS); + } + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + + maybeThrowExceptionForMultiArchCopy( + "Error unpackaging 64 bit native libs for multiarch app.", abi64); + + if (abi64 >= 0) { + // Shared library native libs should be in the APK zip aligned + if (extractLibs && pkg.isLibrary()) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Shared library native lib extraction not supported"); + } + pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64]; + } + + if (abi32 >= 0) { + final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32]; + if (abi64 >= 0) { + if (pkg.use32bitAbi) { + pkg.applicationInfo.secondaryCpuAbi = + pkg.applicationInfo.primaryCpuAbi; + pkg.applicationInfo.primaryCpuAbi = abi; + } else { + pkg.applicationInfo.secondaryCpuAbi = abi; + } + } else { + pkg.applicationInfo.primaryCpuAbi = abi; + } + } + } else { + String[] abiList = (cpuAbiOverride != null) + ? new String[]{cpuAbiOverride} : Build.SUPPORTED_ABIS; + + // Enable gross and lame hacks for apps that are built with old + // SDK tools. We must scan their APKs for renderscript bitcode and + // not launch them if it's present. Don't bother checking on devices + // that don't have 64 bit support. + boolean needsRenderScriptOverride = false; + if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null + && NativeLibraryHelper.hasRenderscriptBitcode(handle)) { + abiList = Build.SUPPORTED_32_BIT_ABIS; + needsRenderScriptOverride = true; + } + + final int copyRet; + if (extractLibs) { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); + copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, + nativeLibraryRoot, abiList, useIsaSpecificSubdirs); + } else { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); + copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList); + } + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + + if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Error unpackaging native libs for app, errorCode=" + copyRet); + } + + if (copyRet >= 0) { + // Shared libraries that have native libs must be multi-architecture + if (pkg.isLibrary()) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Shared library with native libs must be multiarch"); + } + pkg.applicationInfo.primaryCpuAbi = abiList[copyRet]; + } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES + && cpuAbiOverride != null) { + pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride; + } else if (needsRenderScriptOverride) { + pkg.applicationInfo.primaryCpuAbi = abiList[0]; + } + } + } catch (IOException ioe) { + Slog.e(PackageManagerService.TAG, "Unable to get canonical file " + ioe.toString()); + } finally { + IoUtils.closeQuietly(handle); + } + + // Now that we've calculated the ABIs and determined if it's an internal app, + // we will go ahead and populate the nativeLibraryPath. + setNativeLibraryPaths(pkg, PackageManagerService.sAppLib32InstallDir); + } + + /** + * Adjusts ABIs for a set of packages belonging to a shared user so that they all match. + * i.e, so that all packages can be run inside a single process if required. + * + * Optionally, callers can pass in a parsed package via {@code newPackage} in which case + * this function will either try and make the ABI for all packages in + * {@code packagesForUser} match {@code scannedPackage} or will update the ABI of + * {@code scannedPackage} to match the ABI selected for {@code packagesForUser}. This + * variant is used when installing or updating a package that belongs to a shared user. + * + * NOTE: We currently only match for the primary CPU abi string. Matching the secondary + * adds unnecessary complexity. + */ + @Override + @Nullable + public List<String> adjustCpuAbisForSharedUser( + Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage) { + List<String> changedAbiCodePath = null; + String requiredInstructionSet = null; + if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) { + requiredInstructionSet = VMRuntime.getInstructionSet( + scannedPackage.applicationInfo.primaryCpuAbi); + } + + PackageSetting requirer = null; + for (PackageSetting ps : packagesForUser) { + // If packagesForUser contains scannedPackage, we skip it. This will happen + // when scannedPackage is an update of an existing package. Without this check, + // we will never be able to change the ABI of any package belonging to a shared + // user, even if it's compatible with other packages. + if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { + if (ps.primaryCpuAbiString == null) { + continue; + } + + final String instructionSet = + VMRuntime.getInstructionSet(ps.primaryCpuAbiString); + if (requiredInstructionSet != null + && !instructionSet.equals(requiredInstructionSet)) { + // We have a mismatch between instruction sets (say arm vs arm64) warn about + // this but there's not much we can do. + String errorMessage = "Instruction set mismatch, " + + ((requirer == null) ? "[caller]" : requirer) + + " requires " + requiredInstructionSet + " whereas " + ps + + " requires " + instructionSet; + Slog.w(PackageManagerService.TAG, errorMessage); + } + + if (requiredInstructionSet == null) { + requiredInstructionSet = instructionSet; + requirer = ps; + } + } + } + + if (requiredInstructionSet != null) { + String adjustedAbi; + if (requirer != null) { + // requirer != null implies that either scannedPackage was null or that + // scannedPackage did not require an ABI, in which case we have to adjust + // scannedPackage to match the ABI of the set (which is the same as + // requirer's ABI) + adjustedAbi = requirer.primaryCpuAbiString; + if (scannedPackage != null) { + scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi; + } + } else { + // requirer == null implies that we're updating all ABIs in the set to + // match scannedPackage. + adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi; + } + + for (PackageSetting ps : packagesForUser) { + if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { + if (ps.primaryCpuAbiString != null) { + continue; + } + + ps.primaryCpuAbiString = adjustedAbi; + if (ps.pkg != null && ps.pkg.applicationInfo != null + && !TextUtils.equals( + adjustedAbi, ps.pkg.applicationInfo.primaryCpuAbi)) { + ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi; + if (PackageManagerService.DEBUG_ABI_SELECTION) { + Slog.i(PackageManagerService.TAG, + "Adjusting ABI for " + ps.name + " to " + adjustedAbi + + " (requirer=" + + (requirer != null ? requirer.pkg : "null") + + ", scannedPackage=" + + (scannedPackage != null ? scannedPackage : "null") + + ")"); + } + if (changedAbiCodePath == null) { + changedAbiCodePath = new ArrayList<>(); + } + changedAbiCodePath.add(ps.codePathString); + } + } + } + } + return changedAbiCodePath; + } + + private static String calculateBundledApkRoot(final String codePathString) { + final File codePath = new File(codePathString); + final File codeRoot; + if (FileUtils.contains(Environment.getRootDirectory(), codePath)) { + codeRoot = Environment.getRootDirectory(); + } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) { + codeRoot = Environment.getOemDirectory(); + } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) { + codeRoot = Environment.getVendorDirectory(); + } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) { + codeRoot = Environment.getOdmDirectory(); + } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) { + codeRoot = Environment.getProductDirectory(); + } else if (FileUtils.contains(Environment.getSystemExtDirectory(), codePath)) { + codeRoot = Environment.getSystemExtDirectory(); + } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) { + codeRoot = Environment.getOdmDirectory(); + } else { + // Unrecognized code path; take its top real segment as the apk root: + // e.g. /something/app/blah.apk => /something + try { + File f = codePath.getCanonicalFile(); + File parent = f.getParentFile(); // non-null because codePath is a file + File tmp; + while ((tmp = parent.getParentFile()) != null) { + f = parent; + parent = tmp; + } + codeRoot = f; + Slog.w(PackageManagerService.TAG, "Unrecognized code path " + + codePath + " - using " + codeRoot); + } catch (IOException e) { + // Can't canonicalize the code path -- shenanigans? + Slog.w(PackageManagerService.TAG, "Can't canonicalize code path " + codePath); + return Environment.getRootDirectory().getPath(); + } + } + return codeRoot.getPath(); + } + + // Utility method that returns the relative package path with respect + // to the installation directory. Like say for /data/data/com.test-1.apk + // string com.test-1 is returned. + private static String deriveCodePathName(String codePath) { + if (codePath == null) { + return null; + } + final File codeFile = new File(codePath); + final String name = codeFile.getName(); + if (codeFile.isDirectory()) { + return name; + } else if (name.endsWith(".apk") || name.endsWith(".tmp")) { + final int lastDot = name.lastIndexOf('.'); + return name.substring(0, lastDot); + } else { + Slog.w(PackageManagerService.TAG, "Odd, " + codePath + " doesn't look like an APK"); + return null; + } + } + + private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet) throws + PackageManagerException { + if (copyRet < 0) { + if (copyRet != PackageManager.NO_NATIVE_LIBRARIES + && copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { + throw new PackageManagerException(copyRet, message); + } + } + } + +} diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c72b38aa0919..0d1b9c68a214 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -94,14 +94,12 @@ import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT; -import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME; import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME; import static com.android.server.pm.ComponentResolver.RESOLVE_PRIORITY_SORTER; import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; -import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefaultCompilerFilter; import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures; import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists; @@ -277,6 +275,7 @@ import android.view.Display; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; @@ -429,7 +428,7 @@ public class PackageManagerService extends IPackageManager.Stub // user, but by default initialize to this. public static final boolean DEBUG_DEXOPT = false; - private static final boolean DEBUG_ABI_SELECTION = false; + static final boolean DEBUG_ABI_SELECTION = false; private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE; private static final boolean DEBUG_APP_DATA = false; @@ -641,7 +640,7 @@ public class PackageManagerService extends IPackageManager.Stub final boolean mIsPreNMR1Upgrade; final boolean mIsPreQUpgrade; - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean mDexOptDialogShown; // Used for privilege escalation. MUST NOT BE CALLED WITH mPackages @@ -653,7 +652,8 @@ public class PackageManagerService extends IPackageManager.Stub private static final File sAppInstallDir = new File(Environment.getDataDirectory(), "app"); /** Directory where installed application's 32-bit native libraries are copied. */ - private static final File sAppLib32InstallDir = + @VisibleForTesting + static final File sAppLib32InstallDir = new File(Environment.getDataDirectory(), "app-lib"); // ---------------------------------------------------------------- @@ -665,15 +665,18 @@ public class PackageManagerService extends IPackageManager.Stub // ---------------------------------------------------------------- - // Keys are String (package name), values are Package. This also serves - // as the lock for the global state. Methods that must be called with - // this lock held have the prefix "LP". - @GuardedBy("mPackages") + // Lock for global state used when modifying package state or settings. + // Methods that must be called with this lock held have + // the suffix "Locked". Some methods may use the legacy the suffix "LP" + final Object mLock; + + // Keys are String (package name), values are Package. + @GuardedBy("mLock") final ArrayMap<String, PackageParser.Package> mPackages = new ArrayMap<>(); // Keys are isolated uids and values are the uid of the application // that created the isolated proccess. - @GuardedBy("mPackages") + @GuardedBy("mLock") final SparseIntArray mIsolatedOwners = new SparseIntArray(); /** @@ -692,7 +695,7 @@ public class PackageManagerService extends IPackageManager.Stub */ boolean mPromoteSystemApps; - @GuardedBy("mPackages") + @GuardedBy("mLock") final Settings mSettings; /** @@ -702,7 +705,7 @@ public class PackageManagerService extends IPackageManager.Stub * * @see PackageFreezer */ - @GuardedBy("mPackages") + @GuardedBy("mLock") final ArraySet<String> mFrozenPackages = new ArraySet<>(); final ProtectedPackages mProtectedPackages; @@ -719,31 +722,55 @@ public class PackageManagerService extends IPackageManager.Stub private final InstantAppRegistry mInstantAppRegistry; - @GuardedBy("mPackages") + @GuardedBy("mLock") int mChangedPackagesSequenceNumber; /** * List of changed [installed, removed or updated] packages. * mapping from user id -> sequence number -> package name */ - @GuardedBy("mPackages") + @GuardedBy("mLock") final SparseArray<SparseArray<String>> mChangedPackages = new SparseArray<>(); /** * The sequence number of the last change to a package. * mapping from user id -> package name -> sequence number */ - @GuardedBy("mPackages") + @GuardedBy("mLock") final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>(); - @GuardedBy("mPackages") + @GuardedBy("mLock") final private ArraySet<PackageListObserver> mPackageListObservers = new ArraySet<>(); - @GuardedBy("mPackages") + @GuardedBy("mLock") private final SparseIntArray mDefaultPermissionsGrantedUsers = new SparseIntArray(); private final ModuleInfoProvider mModuleInfoProvider; private final ApexManager mApexManager; + private final Injector mInjector; + + /** + * Unit tests will instantiate and / or extend to mock dependencies / behaviors. + */ + @VisibleForTesting + static class Injector { + private final UserManagerInternal mUserManager; + private final PackageAbiHelper mAbiHelper; + + Injector(UserManagerInternal userManager, PackageAbiHelper abiHelper) { + mUserManager = userManager; + mAbiHelper = abiHelper; + } + + public UserManagerInternal getUserManager() { + return mUserManager; + } + + public PackageAbiHelper getAbiHelper() { + return mAbiHelper; + } + } + class PackageParserCallback implements PackageParser.Callback { @Override public final boolean hasFeature(String feature) { return PackageManagerService.this.hasSystemFeature(feature, 0); @@ -813,7 +840,7 @@ public class PackageManagerService extends IPackageManager.Stub String[] getStaticOverlayPaths(String targetPackageName, String targetPath) { List<PackageParser.Package> overlayPackages; synchronized (mInstallLock) { - synchronized (mPackages) { + synchronized (mLock) { overlayPackages = getStaticOverlayPackages( mPackages.values(), targetPackageName); } @@ -837,7 +864,7 @@ public class PackageManagerService extends IPackageManager.Stub List<PackageParser.Package> mOverlayPackages = null; void findStaticOverlayPackages() { - synchronized (mPackages) { + synchronized (mLock) { for (PackageParser.Package p : mPackages.values()) { if (p.mOverlayIsStatic) { if (mOverlayPackages == null) { @@ -1021,7 +1048,7 @@ public class PackageManagerService extends IPackageManager.Stub PackageParser.ActivityIntentInfo filter = filters.get(m); domainsSet.addAll(filter.getHostsList()); } - synchronized (mPackages) { + synchronized (mLock) { if (mSettings.createIntentFilterVerificationIfNeededLPw( packageName, domainsSet) != null) { scheduleWriteSettingsLocked(); @@ -1089,7 +1116,7 @@ public class PackageManagerService extends IPackageManager.Stub final String packageName = ivs.getPackageName(); IntentFilterVerificationInfo ivi; - synchronized (mPackages) { + synchronized (mLock) { ivi = mSettings.getIntentFilterVerificationLPr(packageName); } if (ivi == null) { @@ -1098,7 +1125,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } - synchronized (mPackages) { + synchronized (mLock) { if (verified) { ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS); } else { @@ -1210,7 +1237,7 @@ public class PackageManagerService extends IPackageManager.Stub IntentFilterVerificationState ivs = new IntentFilterVerificationState( verifierUid, userId, packageName); ivs.setPendingState(); - synchronized (mPackages) { + synchronized (mLock) { mIntentFilterVerificationStates.append(verificationId, ivs); mCurrentIntentFilterVerifications.add(verificationId); } @@ -1423,7 +1450,7 @@ public class PackageManagerService extends IPackageManager.Stub int size = 0; int uids[]; Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); - synchronized (mPackages) { + synchronized (mLock) { size = mPendingBroadcasts.size(); if (size <= 0) { // Nothing to be done. Just return @@ -1531,7 +1558,7 @@ public class PackageManagerService extends IPackageManager.Stub } break; case WRITE_SETTINGS: { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); - synchronized (mPackages) { + synchronized (mLock) { removeMessages(WRITE_SETTINGS); removeMessages(WRITE_PACKAGE_RESTRICTIONS); mSettings.writeLPr(); @@ -1541,7 +1568,7 @@ public class PackageManagerService extends IPackageManager.Stub } break; case WRITE_PACKAGE_RESTRICTIONS: { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); - synchronized (mPackages) { + synchronized (mLock) { removeMessages(WRITE_PACKAGE_RESTRICTIONS); for (int userId : mDirtyUsers) { mSettings.writePackageRestrictionsLPr(userId); @@ -1552,7 +1579,7 @@ public class PackageManagerService extends IPackageManager.Stub } break; case WRITE_PACKAGE_LIST: { Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); - synchronized (mPackages) { + synchronized (mLock) { removeMessages(WRITE_PACKAGE_LIST); mSettings.writePackageListLPr(msg.arg1); } @@ -1789,7 +1816,7 @@ public class PackageManagerService extends IPackageManager.Stub res.pkg, callingUid); } - synchronized (mPackages) { + synchronized (mLock) { mInstantAppRegistry.onPackageInstalledLPw(res.pkg, res.newUsers); } @@ -1950,7 +1977,7 @@ public class PackageManagerService extends IPackageManager.Stub if (packageIsBrowser(packageName, userId)) { // If this browser is restored from user's backup, do not clear // default-browser state for this user - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting.getInstallReason(userId) != PackageManager.INSTALL_REASON_DEVICE_RESTORE) { @@ -2007,8 +2034,8 @@ public class PackageManagerService extends IPackageManager.Stub // survive long enough to benefit of background optimizations. for (int userId : firstUserIds) { PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId); - // There's a race currently where some install events may interleave with an uninstall. - // This can lead to package info being null (b/36642664). + // There's a race currently where some install events may interleave with an + // uninstall. This can lead to package info being null (b/36642664). if (info != null) { mDexManager.notifyPackageInstalled(info, userId); } @@ -2078,6 +2105,7 @@ public class PackageManagerService extends IPackageManager.Stub * external/removable/unprotected storage. * @return {@link StorageEnum#TYPE_UNKNOWN} if the package is not stored externally or the * corresponding {@link StorageEnum} storage type value if it is. + * corresponding {@link StorageEnum} storage type value if it is. */ private static int getPackageExternalStorageType(VolumeInfo packageVolume, boolean packageIsExternal) { @@ -2130,7 +2158,7 @@ public class PackageManagerService extends IPackageManager.Stub } // Remove any apps installed on the forgotten volume - synchronized (mPackages) { + synchronized (mLock) { final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(fsUuid); for (PackageSetting ps : packages) { Slog.d(TAG, "Destroying " + ps.name + " because volume was forgotten"); @@ -2206,9 +2234,10 @@ public class PackageManagerService extends IPackageManager.Stub boolean factoryTest, boolean onlyCore) { // Self-check for initial settings. PackageManagerServiceCompilerMapping.checkProperties(); + final Object packageLock = new Object(); PackageManagerService m = new PackageManagerService(context, installer, - factoryTest, onlyCore); + factoryTest, onlyCore, packageLock); m.enableSystemUserPackages(); ServiceManager.addService("package", m); final PackageManagerNative pmn = m.new PackageManagerNative(); @@ -2241,7 +2270,7 @@ public class PackageManagerService extends IPackageManager.Stub List<String> allAps = queryHelper.queryApps(0, /* systemAppsOnly */ false, UserHandle.SYSTEM); final int allAppsSize = allAps.size(); - synchronized (mPackages) { + synchronized (mLock) { for (int i = 0; i < allAppsSize; i++) { String pName = allAps.get(i); PackageSetting pkgSetting = mSettings.mPackages.get(pName); @@ -2300,11 +2329,12 @@ public class PackageManagerService extends IPackageManager.Stub } public PackageManagerService(Context context, Installer installer, boolean factoryTest, - boolean onlyCore) { + boolean onlyCore, Object packageLock) { final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", Trace.TRACE_TAG_PACKAGE_MANAGER); t.traceBegin("create package manager"); - LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES); + mLock = packageLock; + LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); @@ -2313,7 +2343,6 @@ public class PackageManagerService extends IPackageManager.Stub } mContext = context; - mFactoryTest = factoryTest; mOnlyCore = onlyCore; mMetrics = new DisplayMetrics(); @@ -2323,23 +2352,28 @@ public class PackageManagerService extends IPackageManager.Stub t.traceBegin("createSubComponents"); // CHECKSTYLE:OFF IndentationCheck synchronized (mInstallLock) { - synchronized (mPackages) { + synchronized (mLock) { // Expose private service for system components to use. LocalServices.addService( PackageManagerInternal.class, new PackageManagerInternalImpl()); sUserManager = new UserManagerService(context, this, - new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages); + new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), + mLock); mComponentResolver = new ComponentResolver(sUserManager, LocalServices.getService(PackageManagerInternal.class), - mPackages); + mLock); mPermissionManager = PermissionManagerService.create(context, - mPackages /*externalLock*/); + mLock /*externalLock*/); mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr"); mSettings = new Settings(Environment.getDataDirectory(), - mPermissionManager.getPermissionSettings(), mPackages); + mPermissionManager.getPermissionSettings(), mLock); } } + + // TODO(b/137961986): We should pass this via constructor, but would first need to create + // a packages lock that could also be passed in. + mInjector = new Injector(getUserManagerInternal(), new PackageAbiHelperImpl()); // CHECKSTYLE:ON IndentationCheck t.traceEnd(); @@ -2400,7 +2434,7 @@ public class PackageManagerService extends IPackageManager.Stub // CHECKSTYLE:OFF IndentationCheck synchronized (mInstallLock) { // writer - synchronized (mPackages) { + synchronized (mLock) { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); @@ -3048,7 +3082,8 @@ public class PackageManagerService extends IPackageManager.Stub // the rest of the commands above) because there's precious little we // can do about it. A settings error is reported, though. final List<String> changedAbiCodePath = - adjustCpuAbisForSharedUserLPw(setting.packages, null /*scannedPackage*/); + mInjector.getAbiHelper().adjustCpuAbisForSharedUser( + setting.packages, null /*scannedPackage*/); if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) { for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) { final String codePathString = changedAbiCodePath.get(i); @@ -3131,7 +3166,7 @@ public class PackageManagerService extends IPackageManager.Stub int count = 0; for (String pkgName : deferPackages) { PackageParser.Package pkg = null; - synchronized (mPackages) { + synchronized (mLock) { PackageSetting ps = mSettings.getPackageLPr(pkgName); if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) { pkg = ps.pkg; @@ -3278,7 +3313,7 @@ public class PackageManagerService extends IPackageManager.Stub MetricsLogger.histogram(null, "ota_package_manager_init_time", (int) (SystemClock.uptimeMillis() - startTime)); } - } // synchronized (mPackages) + } // synchronized (mLock) } // synchronized (mInstallLock) // CHECKSTYLE:ON IndentationCheck @@ -3294,7 +3329,7 @@ public class PackageManagerService extends IPackageManager.Stub // The initial scanning above does many calls into installd while // holding the mPackages lock, but we're mostly interested in yelling // once we have a booted system. - mInstaller.setWarnIfHeld(mPackages); + mInstaller.setWarnIfHeld(mLock); PackageParser.readConfigUseRoundIcon(mContext.getResources()); @@ -3376,7 +3411,7 @@ public class PackageManagerService extends IPackageManager.Stub try (PackageFreezer freezer = freezePackage(stubPkg.packageName, "setEnabledSetting")) { pkg = installStubPackageLI(stubPkg, parseFlags, 0 /*scanFlags*/); - synchronized (mPackages) { + synchronized (mLock) { prepareAppDataAfterInstallLIF(pkg); try { updateSharedLibrariesLocked(pkg, null, mPackages); @@ -3390,7 +3425,7 @@ public class PackageManagerService extends IPackageManager.Stub // Whoops! Something went very wrong; roll back to the stub and disable the package try (PackageFreezer freezer = freezePackage(stubPkg.packageName, "setEnabledSetting")) { - synchronized (mPackages) { + synchronized (mLock) { // NOTE: Ensure the system package is enabled; even for a compressed stub. // If we don't, installing the system package fails during scan enableSystemPackageLPw(stubPkg); @@ -3403,7 +3438,7 @@ public class PackageManagerService extends IPackageManager.Stub Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.packageName, pme); } finally { // Disable the package; the stub by itself is not runnable - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.packageName); if (stubPs != null) { stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, @@ -3433,7 +3468,7 @@ public class PackageManagerService extends IPackageManager.Stub if (scanFile == null) { throw new PackageManagerException("Unable to decompress stub at " + stubPkg.codePath); } - synchronized (mPackages) { + synchronized (mLock) { mSettings.disableSystemPackageLPw(stubPkg.packageName, true /*replaced*/); } removePackageLI(stubPkg, true /*chatty*/); @@ -3510,7 +3545,7 @@ public class PackageManagerService extends IPackageManager.Stub return dstCodePath; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void updateInstantAppInstallerLocked(String modifiedPackage) { // we're only interested in updating the installer appliction when 1) it's not // already set or 2) the modified package is the installer @@ -3631,7 +3666,7 @@ public class PackageManagerService extends IPackageManager.Stub } private @NonNull String getRequiredSharedLibraryLPr(String name, int version) { - synchronized (mPackages) { + synchronized (mLock) { SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version); if (libraryInfo == null) { throw new IllegalStateException("Missing required shared library:" + name); @@ -3731,7 +3766,7 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return null; } - synchronized (mPackages) { + synchronized (mLock) { final Pair<ComponentName, String> instantAppResolver = getInstantAppResolverLPr(); if (instantAppResolver == null) { return null; @@ -3796,7 +3831,7 @@ public class PackageManagerService extends IPackageManager.Stub return null; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private @Nullable ActivityInfo getInstantAppInstallerLPr() { String[] orderedActions = Build.IS_ENG ? new String[]{ @@ -3863,7 +3898,7 @@ public class PackageManagerService extends IPackageManager.Stub return matches.get(0).getComponentInfo().getComponentName(); } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void primeDomainVerificationsLPw(int userId) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, "Priming domain verifications in user " + userId); @@ -4058,7 +4093,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new SecurityException("Instant applications don't have access to this method"); } final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId); - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) { throw new SecurityException("Package " + packageName + " was not found!"); @@ -4089,7 +4124,7 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUid = Binder.getCallingUid(); mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, false /*checkShell*/, "is package available"); - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Package p = mPackages.get(packageName); if (p != null) { final PackageSetting ps = (PackageSetting) p.mExtras; @@ -4134,7 +4169,7 @@ public class PackageManagerService extends IPackageManager.Stub false /* requireFullPermission */, false /* checkShell */, "get package info"); // reader - synchronized (mPackages) { + synchronized (mLock) { // Normalize package name to handle renamed packages and static libs packageName = resolveInternalPackageNameLPr(packageName, versionCode); @@ -4250,7 +4285,7 @@ public class PackageManagerService extends IPackageManager.Stub * * @see #canViewInstantApps(int, int) */ - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid, @Nullable ComponentName component, @ComponentType int componentType, int userId) { // if we're in an isolated process, get the real calling UID @@ -4308,12 +4343,12 @@ public class PackageManagerService extends IPackageManager.Stub /** * @see #filterAppAccessLPr(PackageSetting, int, ComponentName, int, int) */ - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid, int userId) { return filterAppAccessLPr(ps, callingUid, null, TYPE_UNKNOWN, userId); } - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId, int flags) { // Callers can access only the libs they depend on, otherwise they need to explicitly @@ -4376,7 +4411,7 @@ public class PackageManagerService extends IPackageManager.Stub } final String[] out = new String[names.length]; // reader - synchronized (mPackages) { + synchronized (mLock) { final int callingUserId = UserHandle.getUserId(callingUid); final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId); for (int i=names.length-1; i>=0; i--) { @@ -4403,7 +4438,7 @@ public class PackageManagerService extends IPackageManager.Stub } final String[] out = new String[names.length]; // reader - synchronized (mPackages) { + synchronized (mLock) { final int callingUserId = UserHandle.getUserId(callingUid); final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId); for (int i=names.length-1; i>=0; i--) { @@ -4433,7 +4468,7 @@ public class PackageManagerService extends IPackageManager.Stub false /*requireFullPermission*/, false /*checkShell*/, "getPackageUid"); // reader - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package p = mPackages.get(packageName); if (p != null && p.isMatch(flags)) { PackageSetting ps = (PackageSetting) p.mExtras; @@ -4463,7 +4498,7 @@ public class PackageManagerService extends IPackageManager.Stub false /*requireFullPermission*/, false /*checkShell*/, "getPackageGids"); // reader - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package p = mPackages.get(packageName); if (p != null && p.isMatch(flags)) { PackageSetting ps = (PackageSetting) p.mExtras; @@ -4497,7 +4532,7 @@ public class PackageManagerService extends IPackageManager.Stub return null; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags, int filterCallingUid, int userId) { if (!sUserManager.exists(userId)) return null; @@ -4549,7 +4584,7 @@ public class PackageManagerService extends IPackageManager.Stub } // writer - synchronized (mPackages) { + synchronized (mLock) { // Normalize package name to handle renamed packages and static libs packageName = resolveInternalPackageNameLPr(packageName, PackageManager.VERSION_CODE_HIGHEST); @@ -4587,7 +4622,7 @@ public class PackageManagerService extends IPackageManager.Stub return null; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private String normalizePackageNameLPr(String packageName) { String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName); return normalizedPackageName != null ? normalizedPackageName : packageName; @@ -4742,7 +4777,7 @@ public class PackageManagerService extends IPackageManager.Stub List<VersionedPackage> packagesToDelete = null; final long now = System.currentTimeMillis(); - synchronized (mPackages) { + synchronized (mLock) { final int[] allUsers = sUserManager.getUserIds(); final int libCount = mSharedLibraries.size(); for (int i = 0; i < libCount; i++) { @@ -4980,7 +5015,7 @@ public class PackageManagerService extends IPackageManager.Stub false /* requireFullPermission */, false /* checkShell */, "get activity info"); } - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Activity a = mComponentResolver.getActivity(component); if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a); @@ -5020,7 +5055,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean activitySupportsIntent(ComponentName component, Intent intent, String resolvedType) { - synchronized (mPackages) { + synchronized (mLock) { if (component.equals(mResolveComponentName)) { // The resolver supports EVERYTHING! return true; @@ -5055,7 +5090,7 @@ public class PackageManagerService extends IPackageManager.Stub flags = updateFlagsForComponent(flags, userId, component); mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get receiver info"); - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Activity a = mComponentResolver.getReceiver(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getReceiverInfo " + component + ": " + a); @@ -5096,7 +5131,7 @@ public class PackageManagerService extends IPackageManager.Stub || mContext.checkCallingOrSelfPermission( Manifest.permission.ACCESS_SHARED_LIBRARIES) == PERMISSION_GRANTED; - synchronized (mPackages) { + synchronized (mLock) { List<SharedLibraryInfo> result = null; final int libCount = mSharedLibraries.size(); @@ -5165,7 +5200,7 @@ public class PackageManagerService extends IPackageManager.Stub return null; } - synchronized (mPackages) { + synchronized (mLock) { List<SharedLibraryInfo> result = null; int libraryCount = mSharedLibraries.size(); @@ -5214,7 +5249,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private List<VersionedPackage> getPackagesUsingSharedLibraryLPr( SharedLibraryInfo libInfo, int flags, int userId) { List<VersionedPackage> versionedPackages = null; @@ -5269,7 +5304,7 @@ public class PackageManagerService extends IPackageManager.Stub flags = updateFlagsForComponent(flags, userId, component); mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get service info"); - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Service s = mComponentResolver.getService(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getServiceInfo " + component + ": " + s); @@ -5293,7 +5328,7 @@ public class PackageManagerService extends IPackageManager.Stub flags = updateFlagsForComponent(flags, userId, component); mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get provider info"); - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Provider p = mComponentResolver.getProvider(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getProviderInfo " + component + ": " + p); @@ -5323,7 +5358,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String[] getSystemSharedLibraryNames() { // allow instant applications - synchronized (mPackages) { + synchronized (mLock) { Set<String> libs = null; final int libCount = mSharedLibraries.size(); for (int i = 0; i < libCount; i++) { @@ -5367,7 +5402,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public @NonNull String getServicesSystemSharedLibraryPackageName() { // allow instant applications - synchronized (mPackages) { + synchronized (mLock) { return mServicesSystemSharedLibraryPackageName; } } @@ -5375,12 +5410,12 @@ public class PackageManagerService extends IPackageManager.Stub @Override public @NonNull String getSharedSystemSharedLibraryPackageName() { // allow instant applications - synchronized (mPackages) { + synchronized (mLock) { return mSharedSystemSharedLibraryPackageName; } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void updateSequenceNumberLP(PackageSetting pkgSetting, int[] userList) { for (int i = userList.length - 1; i >= 0; --i) { final int userId = userList[i]; @@ -5413,7 +5448,7 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return null; } - synchronized (mPackages) { + synchronized (mLock) { if (sequenceNumber >= mChangedPackagesSequenceNumber) { return null; } @@ -5487,13 +5522,13 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String getPermissionControllerPackageName() { - synchronized (mPackages) { + synchronized (mLock) { return mRequiredPermissionControllerPackage; } } String getPackageInstallerPackageName() { - synchronized (mPackages) { + synchronized (mLock) { return mRequiredInstallerPackage; } } @@ -5561,7 +5596,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public int checkSignatures(String pkg1, String pkg2) { - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package p1 = mPackages.get(pkg1); final PackageParser.Package p2 = mPackages.get(pkg2); if (p1 == null || p1.mExtras == null @@ -5589,7 +5624,7 @@ public class PackageManagerService extends IPackageManager.Stub final int appId1 = UserHandle.getAppId(uid1); final int appId2 = UserHandle.getAppId(uid2); // reader - synchronized (mPackages) { + synchronized (mLock) { Signature[] s1; Signature[] s2; Object obj = mSettings.getSettingLPr(appId1); @@ -5638,7 +5673,7 @@ public class PackageManagerService extends IPackageManager.Stub public boolean hasSigningCertificate( String packageName, byte[] certificate, @PackageManager.CertificateInputType int type) { - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package p = mPackages.get(packageName); if (p == null || p.mExtras == null) { return false; @@ -5668,7 +5703,7 @@ public class PackageManagerService extends IPackageManager.Stub // Map to base uids. final int appId = UserHandle.getAppId(uid); // reader - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.SigningDetails signingDetails; final Object obj = mSettings.getSettingLPr(appId); if (obj != null) { @@ -5726,7 +5761,7 @@ public class PackageManagerService extends IPackageManager.Stub public List<String> getAllPackages() { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - synchronized (mPackages) { + synchronized (mLock) { if (canViewInstantApps(callingUid, callingUserId)) { return new ArrayList<>(mPackages.keySet()); } @@ -5775,7 +5810,7 @@ public class PackageManagerService extends IPackageManager.Stub final int userId = UserHandle.getUserId(uid); final int appId = UserHandle.getAppId(uid); // reader - synchronized (mPackages) { + synchronized (mLock) { final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { if (isCallerInstantApp) { @@ -5812,7 +5847,7 @@ public class PackageManagerService extends IPackageManager.Stub return null; } final int appId = UserHandle.getAppId(uid); - synchronized (mPackages) { + synchronized (mLock) { final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; @@ -5838,7 +5873,7 @@ public class PackageManagerService extends IPackageManager.Stub return null; } final String[] names = new String[uids.length]; - synchronized (mPackages) { + synchronized (mLock) { for (int i = uids.length - 1; i >= 0; i--) { final int appId = UserHandle.getAppId(uids[i]); final Object obj = mSettings.getSettingLPr(appId); @@ -5869,7 +5904,7 @@ public class PackageManagerService extends IPackageManager.Stub return -1; } // reader - synchronized (mPackages) { + synchronized (mLock) { SharedUserSetting suid; try { suid = mSettings.getSharedUserLPw(sharedUserName, 0, 0, false); @@ -5890,7 +5925,7 @@ public class PackageManagerService extends IPackageManager.Stub return 0; } final int appId = UserHandle.getAppId(uid); - synchronized (mPackages) { + synchronized (mLock) { final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; @@ -5913,7 +5948,7 @@ public class PackageManagerService extends IPackageManager.Stub return 0; } final int appId = UserHandle.getAppId(uid); - synchronized (mPackages) { + synchronized (mLock) { final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; @@ -5936,7 +5971,7 @@ public class PackageManagerService extends IPackageManager.Stub } final int appId = UserHandle.getAppId(uid); // reader - synchronized (mPackages) { + synchronized (mLock) { final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; @@ -6017,7 +6052,7 @@ public class PackageManagerService extends IPackageManager.Stub 0, userId, intent, callingUid, false /*includeInstantApps*/); final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags, userId); - synchronized (mPackages) { + synchronized (mLock) { return findPersistentPreferredActivityLP(intent, resolvedType, flags, query, false, userId); } @@ -6104,7 +6139,7 @@ public class PackageManagerService extends IPackageManager.Stub } // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution. // Or if there's already an ephemeral app installed that handles the action - synchronized (mPackages) { + synchronized (mLock) { final int count = (resolvedActivities == null ? 0 : resolvedActivities.size()); for (int n = 0; n < count; n++) { final ResolveInfo info = resolvedActivities.get(n); @@ -6246,7 +6281,7 @@ public class PackageManagerService extends IPackageManager.Stub return true; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, boolean debug, int userId) { final int N = query.size(); @@ -6316,7 +6351,7 @@ public class PackageManagerService extends IPackageManager.Stub ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, int priority, boolean always, boolean removeMatches, boolean debug, int userId) { - if (Thread.holdsLock(mPackages)) { + if (Thread.holdsLock(mLock)) { Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding mPackages", new Throwable()); } @@ -6331,7 +6366,7 @@ public class PackageManagerService extends IPackageManager.Stub flags, userId, intent, callingUid, false /*includeInstantApps*/); intent = updateIntentForResolve(intent); // writer - synchronized (mPackages) { + synchronized (mLock) { // Try to find a matching persistent preferred activity. ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query, debug, userId); @@ -6535,7 +6570,7 @@ public class PackageManagerService extends IPackageManager.Stub // cross-profile app linking works only towards the parent. final int callingUid = Binder.getCallingUid(); final UserInfo parent = getProfileParent(sourceUserId); - synchronized(mPackages) { + synchronized (mLock) { int flags = updateFlagsForResolve(0, parent.id, intent, callingUid, false /*includeInstantApps*/); CrossProfileDomainInfo xpDomainInfo = getCrossProfileDomainPreferredLpr( @@ -6582,7 +6617,7 @@ public class PackageManagerService extends IPackageManager.Stub * instant, returns {@code null}. */ private String getInstantAppPackageName(int callingUid) { - synchronized (mPackages) { + synchronized (mLock) { // If the caller is an isolated app use the owner's uid for the lookup. if (Process.isIsolated(callingUid)) { callingUid = mIsolatedOwners.get(callingUid); @@ -6673,7 +6708,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean sortResult = false; boolean addInstant = false; List<ResolveInfo> result; - synchronized (mPackages) { + synchronized (mLock) { if (pkgName == null) { List<CrossProfileIntentFilter> matchingFilters = getMatchingCrossProfileIntentFilters(intent, resolvedType, userId); @@ -7112,7 +7147,7 @@ public class PackageManagerService extends IPackageManager.Stub final ArrayList<ResolveInfo> neverList = new ArrayList<>(); final ArrayList<ResolveInfo> matchAllList = new ArrayList<>(); - synchronized (mPackages) { + synchronized (mLock) { final int count = candidates.size(); // First, try to use linked apps. Partition the candidates into four lists: // one for the final results, one for the "do not use ever", one for "undefined status" @@ -7631,7 +7666,7 @@ public class PackageManagerService extends IPackageManager.Stub } // reader - synchronized (mPackages) { + synchronized (mLock) { String pkgName = intent.getPackage(); if (pkgName == null) { final List<ResolveInfo> result = @@ -7735,7 +7770,7 @@ public class PackageManagerService extends IPackageManager.Stub } // reader - synchronized (mPackages) { + synchronized (mLock) { String pkgName = intent.getPackage(); if (pkgName == null) { return applyPostServiceResolutionFilter( @@ -7853,7 +7888,7 @@ public class PackageManagerService extends IPackageManager.Stub } // reader - synchronized (mPackages) { + synchronized (mLock) { String pkgName = intent.getPackage(); if (pkgName == null) { return applyPostContentProviderResolutionFilter( @@ -7931,7 +7966,7 @@ public class PackageManagerService extends IPackageManager.Stub "get installed packages"); // writer - synchronized (mPackages) { + synchronized (mLock) { ArrayList<PackageInfo> list; if (listUninstalled) { list = new ArrayList<>(mSettings.mPackages.size()); @@ -8028,7 +8063,7 @@ public class PackageManagerService extends IPackageManager.Stub final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0; // writer - synchronized (mPackages) { + synchronized (mLock) { ArrayList<PackageInfo> list = new ArrayList<>(); boolean[] tmpBools = new boolean[permissions.length]; if (listUninstalled) { @@ -8074,7 +8109,7 @@ public class PackageManagerService extends IPackageManager.Stub "get installed application info"); // writer - synchronized (mPackages) { + synchronized (mLock) { ArrayList<ApplicationInfo> list; if (listUninstalled) { list = new ArrayList<>(mSettings.mPackages.size()); @@ -8143,7 +8178,7 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId, true /* requireFullPermission */, false /* checkShell */, "getEphemeralApplications"); - synchronized (mPackages) { + synchronized (mLock) { List<InstantAppInfo> instantApps = mInstantAppRegistry .getInstantAppsLPr(userId); if (instantApps != null) { @@ -8162,7 +8197,7 @@ public class PackageManagerService extends IPackageManager.Stub return false; } - synchronized (mPackages) { + synchronized (mLock) { int callingUid = Binder.getCallingUid(); if (Process.isIsolated(callingUid)) { callingUid = mIsolatedOwners.get(callingUid); @@ -8194,7 +8229,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!isCallerSameApp(packageName, Binder.getCallingUid())) { return null; } - synchronized (mPackages) { + synchronized (mLock) { return mInstantAppRegistry.getInstantAppCookieLPw( packageName, userId); } @@ -8212,7 +8247,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!isCallerSameApp(packageName, Binder.getCallingUid())) { return false; } - synchronized (mPackages) { + synchronized (mLock) { return mInstantAppRegistry.setInstantAppCookieLPw( packageName, cookie, userId); } @@ -8232,7 +8267,7 @@ public class PackageManagerService extends IPackageManager.Stub true /* requireFullPermission */, false /* checkShell */, "getInstantAppIcon"); - synchronized (mPackages) { + synchronized (mLock) { return mInstantAppRegistry.getInstantAppIconLPw( packageName, userId); } @@ -8256,7 +8291,7 @@ public class PackageManagerService extends IPackageManager.Stub final ArrayList<ApplicationInfo> finalList = new ArrayList<>(); // reader - synchronized (mPackages) { + synchronized (mLock) { final Iterator<PackageParser.Package> i = mPackages.values().iterator(); final int userId = UserHandle.getCallingUserId(); while (i.hasNext()) { @@ -8302,7 +8337,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) { return null; } - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName); final ComponentName component = new ComponentName(providerInfo.packageName, providerInfo.name); @@ -8337,7 +8372,7 @@ public class PackageManagerService extends IPackageManager.Stub final List<ProviderInfo> matchList = mComponentResolver.queryProviders(processName, metaDataKey, uid, flags, userId); final int listSize = (matchList == null ? 0 : matchList.size()); - synchronized (mPackages) { + synchronized (mLock) { for (int i = 0; i < listSize; i++) { final ProviderInfo providerInfo = matchList.get(i); if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) { @@ -8367,7 +8402,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public InstrumentationInfo getInstrumentationInfo(ComponentName component, int flags) { // reader - synchronized (mPackages) { + synchronized (mLock) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); final PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); @@ -8397,7 +8432,7 @@ public class PackageManagerService extends IPackageManager.Stub ArrayList<InstrumentationInfo> finalList = new ArrayList<>(); // reader - synchronized (mPackages) { + synchronized (mLock) { final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator(); while (i.hasNext()) { final PackageParser.Instrumentation p = i.next(); @@ -8562,7 +8597,7 @@ public class PackageManagerService extends IPackageManager.Stub * Traces a package scan. * @see #scanPackageLI(File, int, int, long, UserHandle) */ - @GuardedBy({"mInstallLock", "mPackages"}) + @GuardedBy({"mInstallLock", "mLock"}) private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]"); @@ -8577,7 +8612,7 @@ public class PackageManagerService extends IPackageManager.Stub * Scans a package and returns the newly parsed package. * Returns {@code null} in case of errors and the error code is stored in mLastScanError */ - @GuardedBy({"mInstallLock", "mPackages"}) + @GuardedBy({"mInstallLock", "mLock"}) private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); @@ -8609,7 +8644,7 @@ public class PackageManagerService extends IPackageManager.Stub * Scans a package and returns the newly parsed package. * @throws PackageManagerException on a parse error. */ - @GuardedBy({"mInstallLock", "mPackages"}) + @GuardedBy({"mInstallLock", "mLock"}) private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) @@ -8705,7 +8740,7 @@ public class PackageManagerService extends IPackageManager.Stub * structures and the package is made available to the rest of the system. * <p>NOTE: The return value should be removed. It's the passed in package object. */ - @GuardedBy({"mInstallLock", "mPackages"}) + @GuardedBy({"mInstallLock", "mLock"}) private PackageParser.Package addForInitLI(PackageParser.Package pkg, @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) @@ -8730,7 +8765,7 @@ public class PackageManagerService extends IPackageManager.Stub pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath); pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); - synchronized (mPackages) { + synchronized (mLock) { renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage); final String realPkgName = getRealPackageName(pkg, renamedPkgName); if (realPkgName != null) { @@ -8791,7 +8826,8 @@ public class PackageManagerService extends IPackageManager.Stub null /* originalPkgSetting */, null, parseFlags, scanFlags, (pkg == mPlatformPackage), user); applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); - final ScanResult scanResult = scanPackageOnlyLI(request, mFactoryTest, -1L); + final ScanResult scanResult = + scanPackageOnlyLI(request, mInjector, mFactoryTest, -1L); if (scanResult.existingSettingCopied && scanResult.request.pkgSetting != null) { scanResult.request.pkgSetting.updateFrom(scanResult.pkgSetting); } @@ -8810,7 +8846,7 @@ public class PackageManagerService extends IPackageManager.Stub // /data. Switch back to the application on /system. // It's safe to assume the application on /system will correctly scan. If not, // there won't be a working copy of the application. - synchronized (mPackages) { + synchronized (mLock) { // just remove the loaded entries from package lists mPackages.remove(pkgSetting.name); } @@ -8825,7 +8861,7 @@ public class PackageManagerService extends IPackageManager.Stub pkgSetting.codePathString, pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting)); args.cleanUpResourcesLI(); - synchronized (mPackages) { + synchronized (mLock) { mSettings.enableSystemPackageLPw(pkgSetting.name); } } @@ -8914,7 +8950,7 @@ public class PackageManagerService extends IPackageManager.Stub final ScanResult scanResult = scanPackageNewLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); if (scanResult.success) { - synchronized (mPackages) { + synchronized (mLock) { boolean appIdCreated = false; try { final String pkgName = scanResult.pkgSetting.name; @@ -8940,7 +8976,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (shouldHideSystemApp) { - synchronized (mPackages) { + synchronized (mLock) { mSettings.disableSystemPackageLPw(pkg.packageName, true); } } @@ -9011,7 +9047,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (doTrim) { final boolean dexOptDialogShown; - synchronized (mPackages) { + synchronized (mLock) { dexOptDialogShown = mDexOptDialogShown; } if (!isFirstBoot() && dexOptDialogShown) { @@ -9052,7 +9088,7 @@ public class PackageManagerService extends IPackageManager.Stub } List<PackageParser.Package> pkgs; - synchronized (mPackages) { + synchronized (mLock) { pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this); } @@ -9180,7 +9216,7 @@ public class PackageManagerService extends IPackageManager.Stub numberOfPackagesVisited, numberOfPackagesToDexopt), true); } catch (RemoteException e) { } - synchronized (mPackages) { + synchronized (mLock) { mDexOptDialogShown = true; } } @@ -9233,7 +9269,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void notifyPackageUse(String packageName, int reason) { - synchronized (mPackages) { + synchronized (mLock) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); if (getInstantAppPackageName(callingUid) != null) { @@ -9249,7 +9285,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void notifyPackageUseLocked(String packageName, int reason) { final PackageParser.Package p = mPackages.get(packageName); if (p == null) { @@ -9336,7 +9372,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean compileLayouts(String packageName) { PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { return false; @@ -9383,7 +9419,7 @@ public class PackageManagerService extends IPackageManager.Stub // if the package can now be considered up to date for the given filter. private int performDexOptInternal(DexoptOptions options) { PackageParser.Package p; - synchronized (mPackages) { + synchronized (mLock) { p = mPackages.get(options.getPackageName()); if (p == null) { // Package could not be found. Report failure. @@ -9404,7 +9440,7 @@ public class PackageManagerService extends IPackageManager.Stub public ArraySet<String> getOptimizablePackages() { ArraySet<String> pkgs = new ArraySet<>(); - synchronized (mPackages) { + synchronized (mLock) { for (PackageParser.Package p : mPackages.values()) { if (PackageDexOptimizer.canOptimizePackage(p)) { pkgs.add(p.packageName); @@ -9439,7 +9475,7 @@ public class PackageManagerService extends IPackageManager.Stub options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY); for (SharedLibraryInfo info : deps) { PackageParser.Package depPackage = null; - synchronized (mPackages) { + synchronized (mLock) { depPackage = mPackages.get(info.getPackageName()); } if (depPackage != null) { @@ -9527,7 +9563,7 @@ public class PackageManagerService extends IPackageManager.Stub List<SharedLibraryInfo> deps = findSharedLibraries(pkg); if (!deps.isEmpty()) { ArrayList<PackageParser.Package> retValue = new ArrayList<>(); - synchronized (mPackages) { + synchronized (mLock) { for (SharedLibraryInfo info : deps) { PackageParser.Package depPackage = mPackages.get(info.getPackageName()); if (depPackage != null) { @@ -9591,7 +9627,7 @@ public class PackageManagerService extends IPackageManager.Stub @Nullable private PackageSetting getSharedLibLatestVersionSetting(@NonNull ScanResult scanResult) { PackageSetting sharedLibPackage = null; - synchronized (mPackages) { + synchronized (mLock) { final SharedLibraryInfo latestSharedLibraVersionLPr = getLatestSharedLibraVersionLPr(scanResult.pkgSetting.pkg); if (latestSharedLibraVersionLPr != null) { @@ -9609,7 +9645,7 @@ public class PackageManagerService extends IPackageManager.Stub PackageWatchdog.getInstance(mContext).writeNow(); // This is the last chance to write out pending restriction settings - synchronized (mPackages) { + synchronized (mLock) { if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) { mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS); for (int userId : mDirtyUsers) { @@ -9623,7 +9659,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void dumpProfiles(String packageName) { PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { throw new IllegalArgumentException("Unknown package: " + packageName); @@ -9649,7 +9685,7 @@ public class PackageManagerService extends IPackageManager.Stub enforceSystemOrRoot("forceDexOpt"); PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { throw new IllegalArgumentException("Unknown package: " + packageName); @@ -9674,7 +9710,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) { if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { Slog.w(TAG, "Unable to update from " + oldPkg.name @@ -9725,7 +9761,7 @@ public class PackageManagerService extends IPackageManager.Stub private void clearAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) { final PackageSetting ps; - synchronized (mPackages) { + synchronized (mLock) { ps = mSettings.mPackages.get(pkg.packageName); } for (int realUserId : resolveUserIds(userId)) { @@ -9753,7 +9789,7 @@ public class PackageManagerService extends IPackageManager.Stub private void destroyAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) { final PackageSetting ps; - synchronized (mPackages) { + synchronized (mLock) { ps = mSettings.mPackages.get(pkg.packageName); } for (int realUserId : resolveUserIds(userId)) { @@ -9820,7 +9856,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void applyDefiningSharedLibraryUpdateLocked( PackageParser.Package pkg, SharedLibraryInfo libInfo, BiConsumer<SharedLibraryInfo, SharedLibraryInfo> action) { @@ -9849,7 +9885,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void addSharedLibraryLPr(PackageParser.Package pkg, Set<String> usesLibraryFiles, SharedLibraryInfo libInfo, PackageParser.Package changingLib) { if (libInfo.getPath() != null) { @@ -9878,7 +9914,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void updateSharedLibrariesLocked(PackageParser.Package pkg, PackageParser.Package changingLib, Map<String, PackageParser.Package> availablePackages) throws PackageManagerException { @@ -9940,7 +9976,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos( @NonNull List<String> requestedLibraries, @Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests, @@ -10050,7 +10086,7 @@ public class PackageManagerService extends IPackageManager.Stub return false; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private ArrayList<PackageParser.Package> updateAllSharedLibrariesLocked( PackageParser.Package updatedPkg, Map<String, PackageParser.Package> availablePackages) { @@ -10110,7 +10146,7 @@ public class PackageManagerService extends IPackageManager.Stub return resultList; } - @GuardedBy({"mInstallLock", "mPackages"}) + @GuardedBy({"mInstallLock", "mLock"}) private List<ScanResult> scanPackageTracedLI(PackageParser.Package pkg, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { @@ -10151,7 +10187,8 @@ public class PackageManagerService extends IPackageManager.Stub } /** The result of a package scan. */ - private static class ScanResult { + @VisibleForTesting + static class ScanResult { /** The request that initiated the scan that produced this result. */ public final ScanRequest request; /** Whether or not the package scan was successful */ @@ -10190,7 +10227,8 @@ public class PackageManagerService extends IPackageManager.Stub } /** A package to be scanned */ - private static class ScanRequest { + @VisibleForTesting + static class ScanRequest { /** The parsed package */ @NonNull public final PackageParser.Package pkg; /** The package this package replaces */ @@ -10325,7 +10363,7 @@ public class PackageManagerService extends IPackageManager.Stub // TODO(b/72378145) Fix this exemption. Force signature apps // to whitelist their privileged permissions just like other // priv-apps. - synchronized (mPackages) { + synchronized (mLock) { PackageSetting platformPkgSetting = mSettings.mPackages.get("android"); if ((compareSignatures(platformPkgSetting.signatures.mSigningDetails.signatures, pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH)) { @@ -10342,7 +10380,7 @@ public class PackageManagerService extends IPackageManager.Stub // the results / removing app data needs to be moved up a level to the callers of this // method. Also, we need to solve the problem of potentially creating a new shared user // setting. That can probably be done later and patch things up after the fact. - @GuardedBy({"mInstallLock", "mPackages"}) + @GuardedBy({"mInstallLock", "mLock"}) private ScanResult scanPackageNewLI(@NonNull PackageParser.Package pkg, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { @@ -10363,7 +10401,7 @@ public class PackageManagerService extends IPackageManager.Stub } scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, pkg); - synchronized (mPackages) { + synchronized (mLock) { applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); assertPackageIsValid(pkg, parseFlags, scanFlags); @@ -10383,7 +10421,7 @@ public class PackageManagerService extends IPackageManager.Stub pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, (pkg == mPlatformPackage), user); - return scanPackageOnlyLI(request, mFactoryTest, currentTime); + return scanPackageOnlyLI(request, mInjector, mFactoryTest, currentTime); } } @@ -10424,7 +10462,7 @@ public class PackageManagerService extends IPackageManager.Stub * This needs to be fixed so, once we get to this point, no errors are * possible and the system is not left in an inconsistent state. */ - @GuardedBy({"mPackages", "mInstallLock"}) + @GuardedBy({"mLock", "mInstallLock"}) private void commitReconciledScanResultLocked(@NonNull ReconciledPackage reconciledPkg) { final ScanResult result = reconciledPkg.scanResult; final ScanRequest request = result.request; @@ -10512,7 +10550,7 @@ public class PackageManagerService extends IPackageManager.Stub if ((scanFlags & SCAN_CHECK_ONLY) != 0) { if (oldPkgSetting != null) { - synchronized (mPackages) { + synchronized (mLock) { mSettings.mPackages.put(oldPkgSetting.name, oldPkgSetting); } } @@ -10553,7 +10591,7 @@ public class PackageManagerService extends IPackageManager.Stub * <p>An original package must be signed identically and it must have the same * shared user [if any]. */ - @GuardedBy("mPackages") + @GuardedBy("mLock") private @Nullable PackageSetting getOriginalPackageLocked(@NonNull PackageParser.Package pkg, @Nullable String renamedPkgName) { if (!isPackageRenamed(pkg, renamedPkgName)) { @@ -10609,15 +10647,21 @@ public class PackageManagerService extends IPackageManager.Stub * method potentially modifies a live {@link PackageSetting} object representing * the package being scanned. This will be resolved in the future. * + * @param injector injector for acquiring dependencies * @param request Information about the package to be scanned * @param isUnderFactoryTest Whether or not the device is under factory test * @param currentTime The current time, in millis * @return The results of the scan */ @GuardedBy("mInstallLock") - private static @NonNull ScanResult scanPackageOnlyLI(@NonNull ScanRequest request, + @VisibleForTesting + @NonNull + static ScanResult scanPackageOnlyLI(@NonNull ScanRequest request, + Injector injector, boolean isUnderFactoryTest, long currentTime) - throws PackageManagerException { + throws PackageManagerException { + final PackageAbiHelper packageAbiHelper = injector.getAbiHelper(); + final UserManagerInternal userManager = injector.getUserManager(); final PackageParser.Package pkg = request.pkg; PackageSetting pkgSetting = request.pkgSetting; final PackageSetting disabledPkgSetting = request.disabledPkgSetting; @@ -10723,7 +10767,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!createNewPackage) { final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0; - setInstantAppForUser(pkgSetting, userId, instantApp, fullApp); + setInstantAppForUser(userManager, pkgSetting, userId, instantApp, fullApp); } // TODO(patb): see if we can do away with disabled check here. if (disabledPkgSetting != null @@ -10769,7 +10813,7 @@ public class PackageManagerService extends IPackageManager.Stub if (needToDeriveAbi) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi"); final boolean extractNativeLibs = !pkg.isLibrary(); - derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs); + packageAbiHelper.derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // Some system apps still use directory structure for native libraries @@ -10777,8 +10821,8 @@ public class PackageManagerService extends IPackageManager.Stub // structure. Try to detect abi based on directory structure. if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && pkg.applicationInfo.primaryCpuAbi == null) { - setBundledAppAbisAndRoots(pkg, pkgSetting); - setNativeLibraryPaths(pkg, sAppLib32InstallDir); + packageAbiHelper.setBundledAppAbisAndRoots(pkg, pkgSetting); + packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); } } else { // This is not a first boot or an upgrade, don't bother deriving the @@ -10787,7 +10831,7 @@ public class PackageManagerService extends IPackageManager.Stub pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings; pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings; - setNativeLibraryPaths(pkg, sAppLib32InstallDir); + packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Using ABIS and native lib paths from settings : " + @@ -10808,7 +10852,7 @@ public class PackageManagerService extends IPackageManager.Stub // ABIs we've determined above. For non-moves, the path will be updated based on the // ABIs we determined during compilation, but the path will depend on the final // package path (after the rename away from the stage path). - setNativeLibraryPaths(pkg, sAppLib32InstallDir); + packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); } // This is a special case for the "system" package, where the ABI is @@ -10862,8 +10906,8 @@ public class PackageManagerService extends IPackageManager.Stub // We also do this *before* we perform dexopt on this package, so that // we can avoid redundant dexopts, and also to make sure we've got the // code and package path correct. - changedAbiCodePath = - adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, pkg); + changedAbiCodePath = packageAbiHelper.adjustCpuAbisForSharedUser( + pkgSetting.sharedUser.packages, pkg); } if (isUnderFactoryTest && pkg.requestedPermissions.contains( @@ -11142,7 +11186,7 @@ public class PackageManagerService extends IPackageManager.Stub final KeySetManagerService ksms = mSettings.mKeySetManagerService; ksms.assertScannedPackageValid(pkg); - synchronized (mPackages) { + synchronized (mLock) { // The special "android" package can only be defined once if (pkg.packageName.equals("android")) { if (mAndroidApplication != null) { @@ -11458,7 +11502,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean addBuiltInSharedLibraryLocked(String path, String name) { if (nonStaticSharedLibExistsLocked(name)) { return false; @@ -11473,7 +11517,7 @@ public class PackageManagerService extends IPackageManager.Stub return true; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean nonStaticSharedLibExistsLocked(String name) { return sharedLibExists(name, SharedLibraryInfo.VERSION_UNDEFINED, mSharedLibraries); } @@ -11487,7 +11531,7 @@ public class PackageManagerService extends IPackageManager.Stub return false; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void commitSharedLibraryInfoLocked(SharedLibraryInfo libraryInfo) { final String name = libraryInfo.getName(); LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name); @@ -11537,7 +11581,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (pkg.packageName.equals("android")) { - synchronized (mPackages) { + synchronized (mLock) { if ((scanFlags & SCAN_CHECK_ONLY) == 0) { // Set up information for our fall-back user intent resolution activity. mPlatformPackage = pkg; @@ -11575,7 +11619,7 @@ public class PackageManagerService extends IPackageManager.Stub ArrayList<PackageParser.Package> clientLibPkgs = null; // writer - synchronized (mPackages) { + synchronized (mLock) { if (!ArrayUtils.isEmpty(reconciledPkg.allowedSharedLibraryInfos)) { for (SharedLibraryInfo info : reconciledPkg.allowedSharedLibraryInfos) { commitSharedLibraryInfoLocked(info); @@ -11621,7 +11665,7 @@ public class PackageManagerService extends IPackageManager.Stub // writer Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings"); - synchronized (mPackages) { + synchronized (mLock) { // We don't expect installation to fail beyond this point // Add the new setting to mSettings @@ -11713,266 +11757,8 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } - /** - * Derive the ABI of a non-system package located at {@code scanFile}. This information - * is derived purely on the basis of the contents of {@code scanFile} and - * {@code cpuAbiOverride}. - * - * If {@code extractLibs} is true, native libraries are extracted from the app if required. - */ - private static void derivePackageAbi(PackageParser.Package pkg, String cpuAbiOverride, - boolean extractLibs) - throws PackageManagerException { - // Give ourselves some initial paths; we'll come back for another - // pass once we've determined ABI below. - setNativeLibraryPaths(pkg, sAppLib32InstallDir); - - // We shouldn't attempt to extract libs from system app when it was not updated. - if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) { - extractLibs = false; - } - - final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir; - final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa; - - NativeLibraryHelper.Handle handle = null; - try { - handle = NativeLibraryHelper.Handle.create(pkg); - // TODO(multiArch): This can be null for apps that didn't go through the - // usual installation process. We can calculate it again, like we - // do during install time. - // - // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally - // unnecessary. - final File nativeLibraryRoot = new File(nativeLibraryRootStr); - - // Null out the abis so that they can be recalculated. - pkg.applicationInfo.primaryCpuAbi = null; - pkg.applicationInfo.secondaryCpuAbi = null; - if (isMultiArch(pkg.applicationInfo)) { - // Warn if we've set an abiOverride for multi-lib packages.. - // By definition, we need to copy both 32 and 64 bit libraries for - // such packages. - if (pkg.cpuAbiOverride != null - && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) { - Slog.w(TAG, "Ignoring abiOverride for multi arch application."); - } - - int abi32 = PackageManager.NO_NATIVE_LIBRARIES; - int abi64 = PackageManager.NO_NATIVE_LIBRARIES; - if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { - if (extractLibs) { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); - abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, - nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, - useIsaSpecificSubdirs); - } else { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); - abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS); - } - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } - - // Shared library native code should be in the APK zip aligned - if (abi32 >= 0 && pkg.isLibrary() && extractLibs) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Shared library native lib extraction not supported"); - } - - maybeThrowExceptionForMultiArchCopy( - "Error unpackaging 32 bit native libs for multiarch app.", abi32); - - if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { - if (extractLibs) { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); - abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, - nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, - useIsaSpecificSubdirs); - } else { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); - abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS); - } - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } - - maybeThrowExceptionForMultiArchCopy( - "Error unpackaging 64 bit native libs for multiarch app.", abi64); - - if (abi64 >= 0) { - // Shared library native libs should be in the APK zip aligned - if (extractLibs && pkg.isLibrary()) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Shared library native lib extraction not supported"); - } - pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64]; - } - - if (abi32 >= 0) { - final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32]; - if (abi64 >= 0) { - if (pkg.use32bitAbi) { - pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi; - pkg.applicationInfo.primaryCpuAbi = abi; - } else { - pkg.applicationInfo.secondaryCpuAbi = abi; - } - } else { - pkg.applicationInfo.primaryCpuAbi = abi; - } - } - } else { - String[] abiList = (cpuAbiOverride != null) ? - new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS; - - // Enable gross and lame hacks for apps that are built with old - // SDK tools. We must scan their APKs for renderscript bitcode and - // not launch them if it's present. Don't bother checking on devices - // that don't have 64 bit support. - boolean needsRenderScriptOverride = false; - if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null && - NativeLibraryHelper.hasRenderscriptBitcode(handle)) { - abiList = Build.SUPPORTED_32_BIT_ABIS; - needsRenderScriptOverride = true; - } - - final int copyRet; - if (extractLibs) { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries"); - copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, - nativeLibraryRoot, abiList, useIsaSpecificSubdirs); - } else { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi"); - copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList); - } - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - - if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Error unpackaging native libs for app, errorCode=" + copyRet); - } - - if (copyRet >= 0) { - // Shared libraries that have native libs must be multi-architecture - if (pkg.isLibrary()) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Shared library with native libs must be multiarch"); - } - pkg.applicationInfo.primaryCpuAbi = abiList[copyRet]; - } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) { - pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride; - } else if (needsRenderScriptOverride) { - pkg.applicationInfo.primaryCpuAbi = abiList[0]; - } - } - } catch (IOException ioe) { - Slog.e(TAG, "Unable to get canonical file " + ioe.toString()); - } finally { - IoUtils.closeQuietly(handle); - } - - // Now that we've calculated the ABIs and determined if it's an internal app, - // we will go ahead and populate the nativeLibraryPath. - setNativeLibraryPaths(pkg, sAppLib32InstallDir); - } - - /** - * Adjusts ABIs for a set of packages belonging to a shared user so that they all match. - * i.e, so that all packages can be run inside a single process if required. - * - * Optionally, callers can pass in a parsed package via {@code newPackage} in which case - * this function will either try and make the ABI for all packages in {@code packagesForUser} - * match {@code scannedPackage} or will update the ABI of {@code scannedPackage} to match - * the ABI selected for {@code packagesForUser}. This variant is used when installing or - * updating a package that belongs to a shared user. - * - * NOTE: We currently only match for the primary CPU abi string. Matching the secondary - * adds unnecessary complexity. - */ - private static @Nullable List<String> adjustCpuAbisForSharedUserLPw( - Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage) { - List<String> changedAbiCodePath = null; - String requiredInstructionSet = null; - if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) { - requiredInstructionSet = VMRuntime.getInstructionSet( - scannedPackage.applicationInfo.primaryCpuAbi); - } - - PackageSetting requirer = null; - for (PackageSetting ps : packagesForUser) { - // If packagesForUser contains scannedPackage, we skip it. This will happen - // when scannedPackage is an update of an existing package. Without this check, - // we will never be able to change the ABI of any package belonging to a shared - // user, even if it's compatible with other packages. - if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { - if (ps.primaryCpuAbiString == null) { - continue; - } - - final String instructionSet = VMRuntime.getInstructionSet(ps.primaryCpuAbiString); - if (requiredInstructionSet != null && !instructionSet.equals(requiredInstructionSet)) { - // We have a mismatch between instruction sets (say arm vs arm64) warn about - // this but there's not much we can do. - String errorMessage = "Instruction set mismatch, " - + ((requirer == null) ? "[caller]" : requirer) - + " requires " + requiredInstructionSet + " whereas " + ps - + " requires " + instructionSet; - Slog.w(TAG, errorMessage); - } - - if (requiredInstructionSet == null) { - requiredInstructionSet = instructionSet; - requirer = ps; - } - } - } - - if (requiredInstructionSet != null) { - String adjustedAbi; - if (requirer != null) { - // requirer != null implies that either scannedPackage was null or that scannedPackage - // did not require an ABI, in which case we have to adjust scannedPackage to match - // the ABI of the set (which is the same as requirer's ABI) - adjustedAbi = requirer.primaryCpuAbiString; - if (scannedPackage != null) { - scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi; - } - } else { - // requirer == null implies that we're updating all ABIs in the set to - // match scannedPackage. - adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi; - } - - for (PackageSetting ps : packagesForUser) { - if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { - if (ps.primaryCpuAbiString != null) { - continue; - } - - ps.primaryCpuAbiString = adjustedAbi; - if (ps.pkg != null && ps.pkg.applicationInfo != null && - !TextUtils.equals(adjustedAbi, ps.pkg.applicationInfo.primaryCpuAbi)) { - ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi; - if (DEBUG_ABI_SELECTION) { - Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi - + " (requirer=" - + (requirer != null ? requirer.pkg : "null") - + ", scannedPackage=" - + (scannedPackage != null ? scannedPackage : "null") - + ")"); - } - if (changedAbiCodePath == null) { - changedAbiCodePath = new ArrayList<>(); - } - changedAbiCodePath.add(ps.codePathString); - } - } - } - } - return changedAbiCodePath; - } - private void setUpCustomResolverActivity(PackageParser.Package pkg) { - synchronized (mPackages) { + synchronized (mLock) { mResolverReplaced = true; // Set up information for custom user intent resolution activity. mResolveActivity.applicationInfo = pkg.applicationInfo; @@ -12022,207 +11808,6 @@ public class PackageManagerService extends IPackageManager.Stub | IntentFilter.MATCH_ADJUSTMENT_NORMAL; } - private static String calculateBundledApkRoot(final String codePathString) { - final File codePath = new File(codePathString); - final File codeRoot; - if (FileUtils.contains(Environment.getRootDirectory(), codePath)) { - codeRoot = Environment.getRootDirectory(); - } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) { - codeRoot = Environment.getOemDirectory(); - } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) { - codeRoot = Environment.getVendorDirectory(); - } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) { - codeRoot = Environment.getOdmDirectory(); - } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) { - codeRoot = Environment.getProductDirectory(); - } else if (FileUtils.contains(Environment.getSystemExtDirectory(), codePath)) { - codeRoot = Environment.getSystemExtDirectory(); - } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) { - codeRoot = Environment.getOdmDirectory(); - } else { - // Unrecognized code path; take its top real segment as the apk root: - // e.g. /something/app/blah.apk => /something - try { - File f = codePath.getCanonicalFile(); - File parent = f.getParentFile(); // non-null because codePath is a file - File tmp; - while ((tmp = parent.getParentFile()) != null) { - f = parent; - parent = tmp; - } - codeRoot = f; - Slog.w(TAG, "Unrecognized code path " - + codePath + " - using " + codeRoot); - } catch (IOException e) { - // Can't canonicalize the code path -- shenanigans? - Slog.w(TAG, "Can't canonicalize code path " + codePath); - return Environment.getRootDirectory().getPath(); - } - } - return codeRoot.getPath(); - } - - /** - * Derive and set the location of native libraries for the given package, - * which varies depending on where and how the package was installed. - */ - private static void setNativeLibraryPaths(PackageParser.Package pkg, File appLib32InstallDir) { - final ApplicationInfo info = pkg.applicationInfo; - final String codePath = pkg.codePath; - final File codeFile = new File(codePath); - final boolean bundledApp = info.isSystemApp() && !info.isUpdatedSystemApp(); - - info.nativeLibraryRootDir = null; - info.nativeLibraryRootRequiresIsa = false; - info.nativeLibraryDir = null; - info.secondaryNativeLibraryDir = null; - - if (isApkFile(codeFile)) { - // Monolithic install - if (bundledApp) { - // If "/system/lib64/apkname" exists, assume that is the per-package - // native library directory to use; otherwise use "/system/lib/apkname". - final String apkRoot = calculateBundledApkRoot(info.sourceDir); - final boolean is64Bit = VMRuntime.is64BitInstructionSet( - getPrimaryInstructionSet(info)); - - // This is a bundled system app so choose the path based on the ABI. - // if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this - // is just the default path. - final String apkName = deriveCodePathName(codePath); - final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME; - info.nativeLibraryRootDir = Environment.buildPath(new File(apkRoot), libDir, - apkName).getAbsolutePath(); - - if (info.secondaryCpuAbi != null) { - final String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME; - info.secondaryNativeLibraryDir = Environment.buildPath(new File(apkRoot), - secondaryLibDir, apkName).getAbsolutePath(); - } - } else { - final String apkName = deriveCodePathName(codePath); - info.nativeLibraryRootDir = new File(appLib32InstallDir, apkName) - .getAbsolutePath(); - } - - info.nativeLibraryRootRequiresIsa = false; - info.nativeLibraryDir = info.nativeLibraryRootDir; - } else { - // Cluster install - info.nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath(); - info.nativeLibraryRootRequiresIsa = true; - - info.nativeLibraryDir = new File(info.nativeLibraryRootDir, - getPrimaryInstructionSet(info)).getAbsolutePath(); - - if (info.secondaryCpuAbi != null) { - info.secondaryNativeLibraryDir = new File(info.nativeLibraryRootDir, - VMRuntime.getInstructionSet(info.secondaryCpuAbi)).getAbsolutePath(); - } - } - } - - /** - * Calculate the abis and roots for a bundled app. These can uniquely - * be determined from the contents of the system partition, i.e whether - * it contains 64 or 32 bit shared libraries etc. We do not validate any - * of this information, and instead assume that the system was built - * sensibly. - */ - private static void setBundledAppAbisAndRoots(PackageParser.Package pkg, - PackageSetting pkgSetting) { - final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath()); - - // If "/system/lib64/apkname" exists, assume that is the per-package - // native library directory to use; otherwise use "/system/lib/apkname". - final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir); - setBundledAppAbi(pkg, apkRoot, apkName); - // pkgSetting might be null during rescan following uninstall of updates - // to a bundled app, so accommodate that possibility. The settings in - // that case will be established later from the parsed package. - // - // If the settings aren't null, sync them up with what we've just derived. - // note that apkRoot isn't stored in the package settings. - if (pkgSetting != null) { - pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; - pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; - } - } - - /** - * Deduces the ABI of a bundled app and sets the relevant fields on the - * parsed pkg object. - * - * @param apkRoot the root of the installed apk, something like {@code /system} or {@code /oem} - * under which system libraries are installed. - * @param apkName the name of the installed package. - */ - private static void setBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) { - final File codeFile = new File(pkg.codePath); - - final boolean has64BitLibs; - final boolean has32BitLibs; - if (isApkFile(codeFile)) { - // Monolithic install - has64BitLibs = (new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath())).exists(); - has32BitLibs = (new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath())).exists(); - } else { - // Cluster install - final File rootDir = new File(codeFile, LIB_DIR_NAME); - if (!ArrayUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS) - && !TextUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS[0])) { - final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_64_BIT_ABIS[0]); - has64BitLibs = (new File(rootDir, isa)).exists(); - } else { - has64BitLibs = false; - } - if (!ArrayUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS) - && !TextUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS[0])) { - final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_32_BIT_ABIS[0]); - has32BitLibs = (new File(rootDir, isa)).exists(); - } else { - has32BitLibs = false; - } - } - - if (has64BitLibs && !has32BitLibs) { - // The package has 64 bit libs, but not 32 bit libs. Its primary - // ABI should be 64 bit. We can safely assume here that the bundled - // native libraries correspond to the most preferred ABI in the list. - - pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; - pkg.applicationInfo.secondaryCpuAbi = null; - } else if (has32BitLibs && !has64BitLibs) { - // The package has 32 bit libs but not 64 bit libs. Its primary - // ABI should be 32 bit. - - pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; - pkg.applicationInfo.secondaryCpuAbi = null; - } else if (has32BitLibs && has64BitLibs) { - // The application has both 64 and 32 bit bundled libraries. We check - // here that the app declares multiArch support, and warn if it doesn't. - // - // We will be lenient here and record both ABIs. The primary will be the - // ABI that's higher on the list, i.e, a device that's configured to prefer - // 64 bit apps will see a 64 bit primary ABI, - - if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0) { - Slog.e(TAG, "Package " + pkg + " has multiple bundled libs, but is not multiarch."); - } - - if (VMRuntime.is64BitInstructionSet(getPreferredInstructionSet())) { - pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; - pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; - } else { - pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; - pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; - } - } else { - pkg.applicationInfo.primaryCpuAbi = null; - pkg.applicationInfo.secondaryCpuAbi = null; - } - } - private void killApplication(String pkgName, int appId, String reason) { killApplication(pkgName, appId, UserHandle.USER_ALL, reason); } @@ -12271,7 +11856,7 @@ public class PackageManagerService extends IPackageManager.Stub } // writer - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package removedPackage = mPackages.remove(packageName); if (removedPackage != null) { cleanPackageDataStructuresLILPw(removedPackage, chatty); @@ -12286,7 +11871,7 @@ public class PackageManagerService extends IPackageManager.Stub } // writer - synchronized (mPackages) { + synchronized (mLock) { // Remove the parent package mPackages.remove(pkg.applicationInfo.packageName); cleanPackageDataStructuresLILPw(pkg, chatty); @@ -12395,7 +11980,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void notifyPackageAdded(String packageName, int uid) { final PackageListObserver[] observers; - synchronized (mPackages) { + synchronized (mLock) { if (mPackageListObservers.size() == 0) { return; } @@ -12411,7 +11996,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void notifyPackageChanged(String packageName, int uid) { final PackageListObserver[] observers; - synchronized (mPackages) { + synchronized (mLock) { if (mPackageListObservers.size() == 0) { return; } @@ -12433,7 +12018,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void notifyPackageRemoved(String packageName, int uid) { final PackageListObserver[] observers; - synchronized (mPackages) { + synchronized (mLock) { if (mPackageListObservers.size() == 0) { return; } @@ -12682,7 +12267,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean sendAdded = false; boolean sendRemoved = false; // writer - synchronized (mPackages) { + synchronized (mLock) { pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null) { return false; @@ -12743,7 +12328,7 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUid = Binder.getCallingUid(); PackageManagerServiceUtils .enforceSystemOrPhoneCaller("setSystemAppHiddenUntilInstalled", callingUid); - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null || !pkgSetting.isSystem()) { return; @@ -12768,7 +12353,7 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUid = Binder.getCallingUid(); PackageManagerServiceUtils .enforceSystemOrPhoneCaller("setSystemAppInstallState", callingUid); - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); // The target app should always be in system if (pkgSetting == null || !pkgSetting.isSystem()) { @@ -12857,7 +12442,7 @@ public class PackageManagerService extends IPackageManager.Stub long callingId = Binder.clearCallingIdentity(); try { // writer - synchronized (mPackages) { + synchronized (mLock) { ps = mSettings.mPackages.get(packageName); if (ps == null) { return true; @@ -12918,7 +12503,7 @@ public class PackageManagerService extends IPackageManager.Stub (installFlags & PackageManager.INSTALL_FULL_APP) != 0; // writer - synchronized (mPackages) { + synchronized (mLock) { pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null) { return PackageManager.INSTALL_FAILED_INVALID_URI; @@ -12948,7 +12533,8 @@ public class PackageManagerService extends IPackageManager.Stub // upgrade app from instant to full; we don't allow app downgrade installed = true; } - setInstantAppForUser(pkgSetting, userId, instantApp, fullApp); + setInstantAppForUser( + getUserManagerInternal(), pkgSetting, userId, instantApp, fullApp); } if (installed) { @@ -12966,7 +12552,7 @@ public class PackageManagerService extends IPackageManager.Stub } } sendPackageAddedForUser(packageName, pkgSetting, userId); - synchronized (mPackages) { + synchronized (mLock) { updateSequenceNumberLP(pkgSetting, new int[]{ userId }); } // start async restore with no post-install since we finish install here @@ -12996,8 +12582,8 @@ public class PackageManagerService extends IPackageManager.Stub } } - static void setInstantAppForUser(PackageSetting pkgSetting, int userId, - boolean instantApp, boolean fullApp) { + static void setInstantAppForUser(UserManagerInternal userManager, PackageSetting pkgSetting, + int userId, boolean instantApp, boolean fullApp) { // no state specified; do nothing if (!instantApp && !fullApp) { return; @@ -13009,7 +12595,7 @@ public class PackageManagerService extends IPackageManager.Stub pkgSetting.setInstantApp(false /*instantApp*/, userId); } } else { - for (int currentUserId : sUserManager.getUserIds()) { + for (int currentUserId : userManager.getUserIds()) { if (instantApp && !pkgSetting.getInstantApp(currentUserId)) { pkgSetting.setInstantApp(true /*instantApp*/, currentUserId); } else if (fullApp && pkgSetting.getInstantApp(currentUserId)) { @@ -13051,7 +12637,7 @@ public class PackageManagerService extends IPackageManager.Stub for (int i = 0; i < packageNames.length; i++) { final String packageName = packageNames[i]; final PackageSetting pkgSetting; - synchronized (mPackages) { + synchronized (mLock) { pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null || filterAppAccessLPr(pkgSetting, callingUid, userId)) { Slog.w(TAG, "Could not find package setting for package: " + packageName @@ -13064,7 +12650,7 @@ public class PackageManagerService extends IPackageManager.Stub unactionedPackages.add(packageName); continue; } - synchronized (mPackages) { + synchronized (mLock) { final int oldDistractionFlags = pkgSetting.getDistractionFlags(userId); if (restrictionFlags != oldDistractionFlags) { pkgSetting.setDistractionFlags(restrictionFlags, userId); @@ -13079,7 +12665,7 @@ public class PackageManagerService extends IPackageManager.Stub new String[changedPackagesList.size()]); sendDistractingPackagesChanged(changedPackages, changedUids.toArray(), userId, restrictionFlags); - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); } } @@ -13143,7 +12729,7 @@ public class PackageManagerService extends IPackageManager.Stub continue; } final PackageSetting pkgSetting; - synchronized (mPackages) { + synchronized (mLock) { pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null || filterAppAccessLPr(pkgSetting, callingUid, userId)) { Slog.w(TAG, "Could not find package setting for package: " + packageName @@ -13156,7 +12742,7 @@ public class PackageManagerService extends IPackageManager.Stub unactionedPackages.add(packageName); continue; } - synchronized (mPackages) { + synchronized (mLock) { pkgSetting.setSuspended(suspended, callingPackage, dialogInfo, appExtras, launcherExtras, userId); } @@ -13170,7 +12756,7 @@ public class PackageManagerService extends IPackageManager.Stub sendPackagesSuspendedForUser( changedPackages, changedUids.toArray(), userId, suspended, launcherExtras); sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, appExtras, userId); - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); } } @@ -13184,7 +12770,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new SecurityException("Calling package " + packageName + " does not belong to calling uid " + callingUid); } - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) { throw new IllegalArgumentException("Unknown target package: " + packageName); @@ -13236,7 +12822,7 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "isPackageSuspendedForUser for user " + userId); - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) { throw new IllegalArgumentException("Unknown target package: " + packageName); @@ -13284,7 +12870,7 @@ public class PackageManagerService extends IPackageManager.Stub private void unsuspendForSuspendingPackages(Predicate<String> packagePredicate, int userId) { final List<String> affectedPackages = new ArrayList<>(); final IntArray affectedUids = new IntArray(); - synchronized (mPackages) { + synchronized (mLock) { for (PackageSetting ps : mSettings.mPackages.values()) { final PackageUserState pus = ps.readUserState(userId); if (pus.suspended && packagePredicate.test(pus.suspendingPackage)) { @@ -13379,7 +12965,7 @@ public class PackageManagerService extends IPackageManager.Stub + "\": required for permissions management"); continue; } - synchronized (mPackages) { + synchronized (mLock) { if (mProtectedPackages.isPackageStateProtected(userId, packageName)) { Slog.w(TAG, "Cannot suspend package \"" + packageName + "\": protected package"); @@ -13537,7 +13123,7 @@ public class PackageManagerService extends IPackageManager.Stub } private int getUidForVerifier(VerifierInfo verifierInfo) { - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName); if (pkg == null) { return -1; @@ -13703,7 +13289,7 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(callingUid) != null) { return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null || filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) { @@ -13719,7 +13305,7 @@ public class PackageManagerService extends IPackageManager.Stub android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); boolean result = false; - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) { return false; @@ -13739,7 +13325,7 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(callingUid) != null) { return ParceledListSlice.emptyList(); } - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) { return ParceledListSlice.emptyList(); @@ -13755,7 +13341,7 @@ public class PackageManagerService extends IPackageManager.Stub } final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null || pkg.activities == null) { return ParceledListSlice.emptyList(); @@ -13797,7 +13383,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } // writer - synchronized (mPackages) { + synchronized (mLock) { PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage); if (targetPackageSetting == null || filterAppAccessLPr( @@ -13879,7 +13465,7 @@ public class PackageManagerService extends IPackageManager.Stub } mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(), callerPackageName); - synchronized (mPackages) { + synchronized (mLock) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null) { throw new IllegalArgumentException("Unknown target package " + packageName); @@ -14424,7 +14010,7 @@ public class PackageManagerService extends IPackageManager.Stub String packageName = pkgLite.packageName; int installLocation = pkgLite.installLocation; // reader - synchronized (mPackages) { + synchronized (mLock) { // Currently installed package which the new package is attempting to replace or // null if no such package is installed. PackageParser.Package installedPkg = mPackages.get(packageName); @@ -14763,7 +14349,7 @@ public class PackageManagerService extends IPackageManager.Stub mPendingEnableRollback.append(enableRollbackToken, this); final int[] installedUsers; - synchronized (mPackages) { + synchronized (mLock) { PackageSetting ps = mSettings.getPackageLPr(pkgLite.packageName); if (ps != null) { installedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), @@ -15201,16 +14787,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet) throws - PackageManagerException { - if (copyRet < 0) { - if (copyRet != PackageManager.NO_NATIVE_LIBRARIES && - copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) { - throw new PackageManagerException(copyRet, message); - } - } - } - /** * Logic to handle movement of existing installed applications. */ @@ -15337,26 +14913,6 @@ public class PackageManagerService extends IPackageManager.Stub return result; } - // Utility method that returns the relative package path with respect - // to the installation directory. Like say for /data/data/com.test-1.apk - // string com.test-1 is returned. - static String deriveCodePathName(String codePath) { - if (codePath == null) { - return null; - } - final File codeFile = new File(codePath); - final String name = codeFile.getName(); - if (codeFile.isDirectory()) { - return name; - } else if (name.endsWith(".apk") || name.endsWith(".tmp")) { - final int lastDot = name.lastIndexOf('.'); - return name.substring(0, lastDot); - } else { - Slog.w(TAG, "Odd, " + codePath + " doesn't look like an APK"); - return null; - } - } - static class PackageInstalledInfo { String name; int uid; @@ -15464,7 +15020,7 @@ public class PackageManagerService extends IPackageManager.Stub final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0; for (int i = 0; i < childCount; i++) { PackageSetting childPs = null; - synchronized (mPackages) { + synchronized (mLock) { childPs = mSettings.getPackageLPr(ps.childPackageNames.get(i)); } if (childPs != null) { @@ -15475,7 +15031,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void enableSystemPackageLPw(PackageParser.Package pkg) { // Enable the parent package mSettings.enableSystemPackageLPw(pkg.packageName); @@ -15487,7 +15043,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean disableSystemPackageLPw(PackageParser.Package oldPkg, PackageParser.Package newPkg) { // Disable the parent package (parent always replaced) @@ -15502,7 +15058,7 @@ public class PackageManagerService extends IPackageManager.Stub return disabled; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void setInstallerPackageNameLPw(PackageParser.Package pkg, String installerPackageName) { // Enable the parent package @@ -15539,7 +15095,7 @@ public class PackageManagerService extends IPackageManager.Stub final String pkgName = pkg.packageName; if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath); - synchronized (mPackages) { + synchronized (mLock) { // NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions mPermissionManager.updatePermissions(pkg.packageName, pkg); // For system-bundled packages, we assume that installing an upgraded version @@ -15631,7 +15187,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy({"mInstallLock", "mPackages"}) + @GuardedBy({"mInstallLock", "mLock"}) private void installPackagesTracedLI(List<InstallRequest> requests) { try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages"); @@ -15774,7 +15330,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private static Map<String, ReconciledPackage> reconcilePackagesLocked( final ReconcileRequest request, KeySetManagerService ksms) throws ReconcileFailure { @@ -16085,7 +15641,7 @@ public class PackageManagerService extends IPackageManager.Stub return true; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void commitPackagesLocked(final CommitRequest request) { // TODO: remove any expected failures from this method; this should only be able to fail due // to unavoidable errors (I/O, etc.) @@ -16151,8 +15707,9 @@ public class PackageManagerService extends IPackageManager.Stub } } else { try { + // Settings will be written during the call to updateSettingsLI(). executeDeletePackageLIF(reconciledPkg.deletePackageAction, packageName, - true, request.mAllUsers, true, pkg); + true, request.mAllUsers, false, pkg); } catch (SystemDeleteException e) { if (Build.IS_ENG) { throw new RuntimeException("Unexpected failure", e); @@ -16288,7 +15845,8 @@ public class PackageManagerService extends IPackageManager.Stub final PrepareResult prepareResult; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage"); - prepareResult = preparePackageLI(request.args, request.installResult); + prepareResult = + preparePackageLI(request.args, request.installResult); } catch (PrepareFailure prepareFailure) { request.installResult.setError(prepareFailure.error, prepareFailure.getMessage()); @@ -16342,7 +15900,7 @@ public class PackageManagerService extends IPackageManager.Stub Collections.unmodifiableMap(mPackages), versionInfos, lastStaticSharedLibSettings); CommitRequest commitRequest = null; - synchronized (mPackages) { + synchronized (mLock) { Map<String, ReconciledPackage> reconciledPackages; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages"); @@ -16363,11 +15921,6 @@ public class PackageManagerService extends IPackageManager.Stub commitPackagesLocked(commitRequest); success = true; } finally { - for (PrepareResult result : prepareResults.values()) { - if (result.freezer != null) { - result.freezer.close(); - } - } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } @@ -16649,7 +16202,7 @@ public class PackageManagerService extends IPackageManager.Stub // If we are installing a clustered package add results for the children if (pkg.childPackages != null) { - synchronized (mPackages) { + synchronized (mLock) { final int childCount = pkg.childPackages.size(); for (int i = 0; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); @@ -16711,7 +16264,7 @@ public class PackageManagerService extends IPackageManager.Stub pp = null; boolean systemApp = false; boolean replace = false; - synchronized (mPackages) { + synchronized (mLock) { // Check if installing already existing package if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { String oldName = mSettings.getRenamedPackageLPr(pkgName); @@ -16812,7 +16365,7 @@ public class PackageManagerService extends IPackageManager.Stub compareRecover); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { - synchronized (mPackages) { + synchronized (mLock) { ksms.removeAppKeySetDataLPw(pkg.packageName); } } @@ -16932,7 +16485,7 @@ public class PackageManagerService extends IPackageManager.Stub scanFlags |= SCAN_NO_DEX; scanFlags |= SCAN_MOVE; - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps == null) { res.setError(INSTALL_FAILED_INTERNAL_ERROR, @@ -16953,7 +16506,7 @@ public class PackageManagerService extends IPackageManager.Stub String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ? args.abiOverride : pkg.cpuAbiOverride); final boolean extractNativeLibs = !pkg.isLibrary(); - derivePackageAbi(pkg, abiOverride, extractNativeLibs); + mInjector.getAbiHelper().derivePackageAbi(pkg, abiOverride, extractNativeLibs); } catch (PackageManagerException pme) { Slog.e(TAG, "Error deriving application ABI", pme); throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR, @@ -17015,7 +16568,7 @@ public class PackageManagerService extends IPackageManager.Stub final int[] allUsers; final int[] installedUsers; - synchronized (mPackages) { + synchronized (mLock) { oldPackage = mPackages.get(pkgName11); existingPackage = oldPackage; if (DEBUG_INSTALL) { @@ -17150,7 +16703,7 @@ public class PackageManagerService extends IPackageManager.Stub } childRemovedRes.isUpdate = false; childRemovedRes.dataRemoved = true; - synchronized (mPackages) { + synchronized (mLock) { if (childPs != null) { childRemovedRes.origUsers = childPs.queryInstalledUsers( allUsers, @@ -17222,7 +16775,7 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg); // TODO(patb): MOVE TO RECONCILE - synchronized (mPackages) { + synchronized (mLock) { renamedPackage = mSettings.getRenamedPackageLPr(pkgName1); if (renamedPackage != null) { // A package with the same name is already installed, though @@ -17274,7 +16827,7 @@ public class PackageManagerService extends IPackageManager.Stub // Collect files we care for fs-verity setup. ArrayMap<String, String> fsverityCandidates = new ArrayMap<>(); if (legacyMode) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(pkg.packageName); if (ps != null && ps.isPrivileged()) { fsverityCandidates.put(pkg.baseCodePath, null); @@ -17401,7 +16954,7 @@ public class PackageManagerService extends IPackageManager.Stub int count = 0; final String packageName = pkg.packageName; - synchronized (mPackages) { + synchronized (mLock) { // If this is a new install and we see that we've already run verification for this // package, we have nothing to do: it means the state was restored from backup. if (!replacing) { @@ -17459,7 +17012,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) { final ComponentName cn = filter.activity.getComponentName(); final String packageName = cn.getPackageName(); @@ -17482,10 +17035,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - private static boolean isMultiArch(ApplicationInfo info) { - return (info.flags & ApplicationInfo.FLAG_MULTIARCH) != 0; - } - private static boolean isExternal(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; } @@ -17494,7 +17043,7 @@ public class PackageManagerService extends IPackageManager.Stub return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; } - private static boolean isSystemApp(PackageParser.Package pkg) { + static boolean isSystemApp(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } @@ -17575,7 +17124,7 @@ public class PackageManagerService extends IPackageManager.Stub final String packageName = versionedPackage.getPackageName(); final long versionCode = versionedPackage.getLongVersionCode(); final String internalPackageName; - synchronized (mPackages) { + synchronized (mLock) { // Normalize package name to handle renamed packages and static libs internalPackageName = resolveInternalPackageNameLPr(packageName, versionCode); } @@ -17688,7 +17237,7 @@ public class PackageManagerService extends IPackageManager.Stub return pkg.packageName; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private String resolveInternalPackageNameLPr(String packageName, long versionCode) { // Handle renamed packages String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName); @@ -17899,7 +17448,7 @@ public class PackageManagerService extends IPackageManager.Stub int[] allUsers; /** enabled state of the uninstalled application */ final int origEnabledState; - synchronized (mPackages) { + synchronized (mLock) { uninstalledPs = mSettings.mPackages.get(packageName); if (uninstalledPs == null) { Slog.w(TAG, "Not removing non-existent package " + packageName); @@ -17965,7 +17514,7 @@ public class PackageManagerService extends IPackageManager.Stub res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers, deleteFlags | PackageManager.DELETE_CHATTY, info, true, null); } - synchronized (mPackages) { + synchronized (mLock) { if (res) { if (pkg != null) { mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers); @@ -17993,7 +17542,7 @@ public class PackageManagerService extends IPackageManager.Stub final PackageParser.Package stubPkg = (disabledSystemPs == null) ? null : disabledSystemPs.pkg; if (stubPkg != null && stubPkg.isStub) { - synchronized (mPackages) { + synchronized (mLock) { // restore the enabled state of the stub; the state is overwritten when // the stub is uninstalled final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.packageName); @@ -18202,7 +17751,7 @@ public class PackageManagerService extends IPackageManager.Stub if (deletedPs != null) { if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) { final SparseBooleanArray changedUsers = new SparseBooleanArray(); - synchronized (mPackages) { + synchronized (mLock) { clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); clearDefaultBrowserIfNeeded(packageName); mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); @@ -18258,7 +17807,7 @@ public class PackageManagerService extends IPackageManager.Stub } } } - synchronized (mPackages) { + synchronized (mLock) { // can downgrade to reader if (writeSettings) { // Save settings now @@ -18399,7 +17948,7 @@ public class PackageManagerService extends IPackageManager.Stub outInfo, writeSettings, disabledPs.pkg); // writer - synchronized (mPackages) { + synchronized (mLock) { // NOTE: The system package always needs to be enabled; even if it's for // a compressed stub. If we don't, installing the system package fails // during scan [scanning checks the disabled packages]. We will reverse @@ -18479,7 +18028,7 @@ public class PackageManagerService extends IPackageManager.Stub prepareAppDataAfterInstallLIF(pkg); // writer - synchronized (mPackages) { + synchronized (mLock) { PackageSetting ps = mSettings.mPackages.get(pkg.packageName); // Propagate the permissions state as we do not want to drop on the floor @@ -18528,7 +18077,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean deleteCodeAndResources, int flags, int[] allUserHandles, PackageRemovedInfo outInfo, boolean writeSettings, PackageParser.Package replacingPackage) { - synchronized (mPackages) { + synchronized (mLock) { if (outInfo != null) { outInfo.uid = ps.appId; } @@ -18555,7 +18104,7 @@ public class PackageManagerService extends IPackageManager.Stub final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0; for (int i = 0; i < childCount; i++) { PackageSetting childPs; - synchronized (mPackages) { + synchronized (mLock) { childPs = mSettings.getPackageLPr(ps.childPackageNames.get(i)); } if (childPs != null) { @@ -18586,7 +18135,7 @@ public class PackageManagerService extends IPackageManager.Stub int userId) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DELETE_PACKAGES, null); - synchronized (mPackages) { + synchronized (mLock) { // Cannot block uninstall of static shared libs as they are // considered a part of the using app (emulating static linking). // Also static libs are installed always on internal storage. @@ -18604,7 +18153,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean getBlockUninstallForUser(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) { return false; @@ -18616,7 +18165,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean setRequiredForSystemUser(String packageName, boolean systemUserApp) { enforceSystemOrRoot("setRequiredForSystemUser can only be run by the system or root"); - synchronized (mPackages) { + synchronized (mLock) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null) { Log.w(TAG, "Package doesn't exist: " + packageName); @@ -18654,7 +18203,7 @@ public class PackageManagerService extends IPackageManager.Stub * deleted, {@code null} otherwise. */ @Nullable - @GuardedBy("mPackages") + @GuardedBy("mLock") private static DeletePackageAction mayDeletePackageLocked( PackageRemovedInfo outInfo, PackageSetting ps, @Nullable PackageSetting disabledPs, @Nullable PackageSetting[] children, int flags, UserHandle user) { @@ -18702,7 +18251,7 @@ public class PackageManagerService extends IPackageManager.Stub PackageRemovedInfo outInfo, boolean writeSettings, PackageParser.Package replacingPackage) { final DeletePackageAction action; - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps); PackageSetting[] children = mSettings.getChildSettingsLPr(ps); @@ -18754,7 +18303,7 @@ public class PackageManagerService extends IPackageManager.Stub : UserHandle.USER_ALL; clearPackageStateForUserLIF(ps, removedUserId, outInfo, flags); - synchronized (mPackages) { + synchronized (mLock) { markPackageUninstalledForUserLPw(ps, user); scheduleWritePackageRestrictionsLocked(user); } @@ -18773,7 +18322,7 @@ public class PackageManagerService extends IPackageManager.Stub // they have set the special DELETE_SYSTEM_APP which requests different // semantics than normal for uninstalling system apps. final boolean clearPackageStateAndReturn; - synchronized (mPackages) { + synchronized (mLock) { markPackageUninstalledForUserLPw(ps, user); if (!systemApp) { // Do not uninstall the APK if an app should be cached @@ -18803,7 +18352,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (clearPackageStateAndReturn) { clearPackageStateForUserLIF(ps, userId, outInfo, flags); - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(user); } return; @@ -18813,7 +18362,7 @@ public class PackageManagerService extends IPackageManager.Stub // If we are deleting a composite package for all users, keep track // of result for each child. if (ps.childPackageNames != null && outInfo != null) { - synchronized (mPackages) { + synchronized (mLock) { final int childCount = ps.childPackageNames.size(); outInfo.removedChildPackages = new ArrayMap<>(childCount); for (int i = 0; i < childCount; i++) { @@ -18846,7 +18395,7 @@ public class PackageManagerService extends IPackageManager.Stub if (outInfo != null) { outInfo.removedForAllUsers = mPackages.get(ps.name) == null; if (outInfo.removedChildPackages != null) { - synchronized (mPackages) { + synchronized (mLock) { final int childCount = outInfo.removedChildPackages.size(); for (int i = 0; i < childCount; i++) { PackageRemovedInfo childInfo = outInfo.removedChildPackages.valueAt(i); @@ -18861,7 +18410,7 @@ public class PackageManagerService extends IPackageManager.Stub // child packages that appeared as they are declared in the system // app but were not declared in the update. if (systemApp) { - synchronized (mPackages) { + synchronized (mLock) { PackageSetting updatedPs = mSettings.getPackageLPr(ps.name); final int childCount = (updatedPs.childPackageNames != null) ? updatedPs.childPackageNames.size() : 0; @@ -18889,7 +18438,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void markPackageUninstalledForUserLPw(PackageSetting ps, UserHandle user) { final int[] userIds = (user == null || user.getIdentifier() == UserHandle.USER_ALL) ? sUserManager.getUserIds() : new int[] {user.getIdentifier()}; @@ -18923,7 +18472,7 @@ public class PackageManagerService extends IPackageManager.Stub private void clearPackageStateForUserLIF(PackageSetting ps, int userId, PackageRemovedInfo outInfo, int flags) { final PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(ps.name); } @@ -18946,7 +18495,7 @@ public class PackageManagerService extends IPackageManager.Stub if (changedUsers.size() > 0) { updateDefaultHomeNotLocked(changedUsers); postPreferredActivityChangedBroadcast(nextUserId); - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(nextUserId); } } @@ -18976,7 +18525,7 @@ public class PackageManagerService extends IPackageManager.Stub enforceSystemOrRoot("Only the system can clear all profile data"); final PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); } @@ -19014,7 +18563,7 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mInstallLock) { succeeded = clearApplicationUserDataLIF(packageName, userId); } - synchronized (mPackages) { + synchronized (mLock) { mInstantAppRegistry.deleteInstantApplicationMetadataLPw( packageName, userId); } @@ -19053,7 +18602,7 @@ public class PackageManagerService extends IPackageManager.Stub // Try finding details about the requested package PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { final PackageSetting ps = mSettings.mPackages.get(packageName); @@ -19148,7 +18697,7 @@ public class PackageManagerService extends IPackageManager.Stub android.Manifest.permission.ACCESS_INSTANT_APPS); final PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); } @@ -19191,7 +18740,7 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mInstallLock") private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) { final PackageSetting ps; - synchronized (mPackages) { + synchronized (mLock) { ps = mSettings.mPackages.get(packageName); if (ps == null) { Slog.w(TAG, "Failed to find settings for " + packageName); @@ -19223,7 +18772,7 @@ public class PackageManagerService extends IPackageManager.Stub return true; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private int getUidTargetSdkVersionLockedLPr(int uid) { final int appId = UserHandle.getAppId(uid); final Object obj = mSettings.getSettingLPr(appId); @@ -19248,7 +18797,7 @@ public class PackageManagerService extends IPackageManager.Stub return Build.VERSION_CODES.CUR_DEVELOPMENT; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private int getPackageTargetSdkVersionLockedLPr(String packageName) { final PackageParser.Package p = mPackages.get(packageName); if (p != null) { @@ -19292,7 +18841,7 @@ public class PackageManagerService extends IPackageManager.Stub + userId + ":"); filter.dump(new LogPrinter(Log.INFO, TAG), " "); } - synchronized (mPackages) { + synchronized (mLock) { final PreferredIntentResolver pir = mSettings.editPreferredActivitiesLPw(userId); pir.addFilter(new PreferredActivity(filter, match, set, activity, always)); scheduleWritePackageRestrictionsLocked(userId); @@ -19344,7 +18893,7 @@ public class PackageManagerService extends IPackageManager.Stub if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { - synchronized (mPackages) { + synchronized (mLock) { if (getUidTargetSdkVersionLockedLPr(callingUid) < Build.VERSION_CODES.FROYO) { Slog.w(TAG, "Ignoring replacePreferredActivity() from uid " @@ -19356,7 +18905,7 @@ public class PackageManagerService extends IPackageManager.Stub android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); } - synchronized (mPackages) { + synchronized (mLock) { final PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId); if (pir != null) { // Get all of the existing entries that exactly match this filter. @@ -19420,7 +18969,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } // writer - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null || !isCallerSameApp(packageName, callingUid)) { if (mContext.checkCallingOrSelfPermission( @@ -19448,14 +18997,14 @@ public class PackageManagerService extends IPackageManager.Stub if (changedUsers.size() > 0) { updateDefaultHomeNotLocked(changedUsers); postPreferredActivityChangedBroadcast(callingUserId); - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(callingUserId); } } } /** This method takes a specific user id as well as UserHandle.USER_ALL. */ - @GuardedBy("mPackages") + @GuardedBy("mLock") private void clearPackagePreferredActivitiesLPw(String packageName, @NonNull SparseBooleanArray outUserChanged, int userId) { ArrayList<PreferredActivity> removed = null; @@ -19490,7 +19039,7 @@ public class PackageManagerService extends IPackageManager.Stub } /** This method takes a specific user id as well as UserHandle.USER_ALL. */ - @GuardedBy("mPackages") + @GuardedBy("mLock") private void clearIntentFilterVerificationsLPw(int userId) { final int packageCount = mPackages.size(); for (int i = 0; i < packageCount; i++) { @@ -19500,7 +19049,7 @@ public class PackageManagerService extends IPackageManager.Stub } /** This method takes a specific user id as well as UserHandle.USER_ALL. */ - @GuardedBy("mPackages") + @GuardedBy("mLock") void clearIntentFilterVerificationsLPw(String packageName, int userId) { if (userId == UserHandle.USER_ALL) { if (mSettings.removeIntentFilterVerificationLPw(packageName, @@ -19544,7 +19093,7 @@ public class PackageManagerService extends IPackageManager.Stub if (changedUsers.size() > 0) { postPreferredActivityChangedBroadcast(userId); } - synchronized (mPackages) { + synchronized (mLock) { mSettings.applyDefaultPreferredAppsLPw(userId); clearIntentFilterVerificationsLPw(userId); primeDomainVerificationsLPw(userId); @@ -19557,7 +19106,7 @@ public class PackageManagerService extends IPackageManager.Stub // callbacks to the package manager to request a default app reset. mPermissionManager.setDefaultBrowser(null, true, true, userId); resetNetworkPolicies(userId); - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); } } finally { @@ -19574,7 +19123,7 @@ public class PackageManagerService extends IPackageManager.Stub int num = 0; final int userId = UserHandle.getCallingUserId(); // reader - synchronized (mPackages) { + synchronized (mLock) { PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId); if (pir != null) { final Iterator<PreferredActivity> it = pir.filterIterator(); @@ -19614,7 +19163,7 @@ public class PackageManagerService extends IPackageManager.Stub + " for user " + userId + ":"); filter.dump(new LogPrinter(Log.INFO, TAG), " "); } - synchronized (mPackages) { + synchronized (mLock) { mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter( new PersistentPreferredActivity(filter, activity)); scheduleWritePackageRestrictionsLocked(userId); @@ -19632,7 +19181,7 @@ public class PackageManagerService extends IPackageManager.Stub } ArrayList<PersistentPreferredActivity> removed = null; boolean changed = false; - synchronized (mPackages) { + synchronized (mLock) { for (int i=0; i<mSettings.mPersistentPreferredActivities.size(); i++) { final int thisUserId = mSettings.mPersistentPreferredActivities.keyAt(i); PersistentPreferredIntentResolver ppir = mSettings.mPersistentPreferredActivities @@ -19663,7 +19212,7 @@ public class PackageManagerService extends IPackageManager.Stub if (changed) { updateDefaultHomeNotLocked(userId); postPreferredActivityChangedBroadcast(userId); - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); } } @@ -19722,7 +19271,7 @@ public class PackageManagerService extends IPackageManager.Stub serializer.startDocument(null, true); serializer.startTag(null, TAG_PREFERRED_BACKUP); - synchronized (mPackages) { + synchronized (mLock) { mSettings.writePreferredActivitiesLPr(serializer, userId, true); } @@ -19750,7 +19299,7 @@ public class PackageManagerService extends IPackageManager.Stub parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name()); restoreFromXml(parser, userId, TAG_PREFERRED_BACKUP, (readParser, readUserId) -> { - synchronized (mPackages) { + synchronized (mLock) { mSettings.readPreferredActivitiesLPw(readParser, readUserId); } updateDefaultHomeNotLocked(readUserId); @@ -19780,7 +19329,7 @@ public class PackageManagerService extends IPackageManager.Stub serializer.startDocument(null, true); serializer.startTag(null, TAG_DEFAULT_APPS); - synchronized (mPackages) { + synchronized (mLock) { mSettings.writeDefaultAppsLPr(serializer, userId); } @@ -19809,7 +19358,7 @@ public class PackageManagerService extends IPackageManager.Stub restoreFromXml(parser, userId, TAG_DEFAULT_APPS, (parser1, userId1) -> { final String defaultBrowser; - synchronized (mPackages) { + synchronized (mLock) { mSettings.readDefaultAppsLPw(parser1, userId1); defaultBrowser = mSettings.removeDefaultBrowserPackageNameLPw(userId1); } @@ -19838,7 +19387,7 @@ public class PackageManagerService extends IPackageManager.Stub serializer.startDocument(null, true); serializer.startTag(null, TAG_INTENT_FILTER_VERIFICATION); - synchronized (mPackages) { + synchronized (mLock) { mSettings.writeAllDomainVerificationsLPr(serializer, userId); } @@ -19866,7 +19415,7 @@ public class PackageManagerService extends IPackageManager.Stub parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name()); restoreFromXml(parser, userId, TAG_INTENT_FILTER_VERIFICATION, (parser1, userId1) -> { - synchronized (mPackages) { + synchronized (mLock) { mSettings.readAllDomainVerificationsLPr(parser1, userId1); mSettings.writeLPr(); } @@ -19891,7 +19440,7 @@ public class PackageManagerService extends IPackageManager.Stub Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions"); return; } - synchronized (mPackages) { + synchronized (mLock) { CrossProfileIntentFilter newFilter = new CrossProfileIntentFilter(intentFilter, ownerPackage, targetUserId, flags); CrossProfileIntentResolver resolver = @@ -19919,7 +19468,7 @@ public class PackageManagerService extends IPackageManager.Stub enforceOwnerRights(ownerPackage, callingUid); PackageManagerServiceUtils.enforceShellRestriction( UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId); - synchronized (mPackages) { + synchronized (mLock) { CrossProfileIntentResolver resolver = mSettings.editCrossProfileIntentResolverLPw(sourceUserId); ArraySet<CrossProfileIntentFilter> set = @@ -20071,7 +19620,7 @@ public class PackageManagerService extends IPackageManager.Stub /** <b>must not hold {@link #mPackages}</b> */ private void updateDefaultHomeNotLocked(SparseBooleanArray userIds) { - if (Thread.holdsLock(mPackages)) { + if (Thread.holdsLock(mLock)) { Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding mPackages", new Throwable()); } @@ -20087,7 +19636,7 @@ public class PackageManagerService extends IPackageManager.Stub * @return Whether the ACTION_PREFERRED_ACTIVITY_CHANGED broadcast has been scheduled. */ private boolean updateDefaultHomeNotLocked(int userId) { - if (Thread.holdsLock(mPackages)) { + if (Thread.holdsLock(mLock)) { Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding mPackages", new Throwable()); } @@ -20276,7 +19825,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void setUpdateAvailable(String packageName, boolean updateAvailable) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting != null) { pkgSetting.setUpdateAvailable(updateAvailable); @@ -20321,7 +19870,7 @@ public class PackageManagerService extends IPackageManager.Stub ArrayList<String> components; // reader - synchronized (mPackages) { + synchronized (mLock) { pkgSetting = mSettings.mPackages.get(packageName); if (pkgSetting == null) { if (!isCallerInstantApp) { @@ -20368,7 +19917,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new SecurityException("Cannot disable a system-generated component"); } - synchronized (mPackages) { + synchronized (mLock) { if (callingUid == Process.SHELL_UID && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) { // Shell can only change whole packages between ENABLED and DISABLED_USER states @@ -20393,7 +19942,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (className == null) { // We're dealing with an application/package level state change - synchronized (mPackages) { + synchronized (mLock) { if (pkgSetting.getEnabled(userId) == newState) { // Nothing to do return; @@ -20417,11 +19966,11 @@ public class PackageManagerService extends IPackageManager.Stub // Don't care about who enables an app. callingPackage = null; } - synchronized (mPackages) { + synchronized (mLock) { pkgSetting.setEnabled(newState, userId, callingPackage); } } else { - synchronized (mPackages) { + synchronized (mLock) { // We're dealing with a component level state change // First, verify that this is a valid class name. PackageParser.Package pkg = pkgSetting.pkg; @@ -20458,7 +20007,7 @@ public class PackageManagerService extends IPackageManager.Stub } } } - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); updateSequenceNumberLP(pkgSetting, new int[] { userId }); final long callingId = Binder.clearCallingIdentity(); @@ -20519,7 +20068,7 @@ public class PackageManagerService extends IPackageManager.Stub } mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission*/, false /* checkShell */, "flushPackageRestrictions"); - synchronized (mPackages) { + synchronized (mLock) { mSettings.writePackageRestrictionsLPr(userId); mDirtyUsers.remove(userId); if (mDirtyUsers.isEmpty()) { @@ -20566,7 +20115,7 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, true /* checkShell */, "stop package"); // writer - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (!filterAppAccessLPr(ps, callingUid, userId) && mSettings.setPackageStoppedStateLPw(this, packageName, stopped, @@ -20579,7 +20128,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String getInstallerPackageName(String packageName) { final int callingUid = Binder.getCallingUid(); - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) { return null; @@ -20594,7 +20143,7 @@ public class PackageManagerService extends IPackageManager.Stub public boolean isOrphaned(String packageName) { // reader - synchronized (mPackages) { + synchronized (mLock) { if (!mPackages.containsKey(packageName)) { return false; } @@ -20609,7 +20158,7 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get enabled"); // reader - synchronized (mPackages) { + synchronized (mLock) { if (filterAppAccessLPr(mSettings.getPackageLPr(packageName), callingUid, userId)) { return COMPONENT_ENABLED_STATE_DISABLED; } @@ -20624,7 +20173,7 @@ public class PackageManagerService extends IPackageManager.Stub int callingUid = Binder.getCallingUid(); mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, false /*checkShell*/, "getComponentEnabled"); - synchronized (mPackages) { + synchronized (mLock) { if (filterAppAccessLPr(mSettings.getPackageLPr(component.getPackageName()), callingUid, component, TYPE_UNKNOWN, userId)) { return COMPONENT_ENABLED_STATE_DISABLED; @@ -20686,7 +20235,7 @@ public class PackageManagerService extends IPackageManager.Stub Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled); } - synchronized (mPackages) { + synchronized (mLock) { // Verify that all of the preferred activity components actually // exist. It is possible for applications to be updated and at // that point remove a previously declared activity component that @@ -20722,7 +20271,7 @@ public class PackageManagerService extends IPackageManager.Stub // Now that we've scanned all packages, and granted any default // permissions, ensure permissions are updated. Beware of dragons if you // try optimizing this. - synchronized (mPackages) { + synchronized (mLock) { mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false); } @@ -21017,7 +20566,7 @@ public class PackageManagerService extends IPackageManager.Stub } else if ("service-permissions".equals(cmd)) { dumpState.setDump(DumpState.DUMP_SERVICE_PERMISSIONS); } else if ("write".equals(cmd)) { - synchronized (mPackages) { + synchronized (mLock) { mSettings.writeLPr(); pw.println("Settings written."); return; @@ -21030,7 +20579,7 @@ public class PackageManagerService extends IPackageManager.Stub } // reader - synchronized (mPackages) { + synchronized (mLock) { if (dumpState.isDumping(DumpState.DUMP_VERSION) && packageName == null) { if (!checkin) { if (dumpState.onTitlePrinted()) @@ -21409,7 +20958,7 @@ public class PackageManagerService extends IPackageManager.Stub private void dumpProto(FileDescriptor fd) { final ProtoOutputStream proto = new ProtoOutputStream(fd); - synchronized (mPackages) { + synchronized (mLock) { final long requiredVerifierPackageToken = proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE); proto.write(PackageServiceDumpProto.PackageShortProto.NAME, mRequiredVerifierPackage); @@ -21481,7 +21030,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") @SuppressWarnings("resource") private void dumpDexoptStateLPr(PrintWriter pw, String packageName) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); @@ -21510,7 +21059,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") @SuppressWarnings("resource") private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); @@ -21660,7 +21209,7 @@ public class PackageManagerService extends IPackageManager.Stub final VersionInfo ver; final List<PackageSetting> packages; - synchronized (mPackages) { + synchronized (mLock) { ver = mSettings.findOrCreateVersion(volumeUuid); packages = mSettings.getVolumePackagesLPr(volumeUuid); } @@ -21710,7 +21259,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - synchronized (mPackages) { + synchronized (mLock) { final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion); if (sdkUpdated) { logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to " @@ -21746,7 +21295,7 @@ public class PackageManagerService extends IPackageManager.Stub final ArrayList<ApplicationInfo> unloaded = new ArrayList<>(); synchronized (mInstallLock) { - synchronized (mPackages) { + synchronized (mLock) { final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(volumeUuid); for (PackageSetting ps : packages) { if (ps.pkg == null) continue; @@ -21791,7 +21340,7 @@ public class PackageManagerService extends IPackageManager.Stub private void assertPackageKnownAndInstalled(String volumeUuid, String packageName, int userId) throws PackageManagerException { - synchronized (mPackages) { + synchronized (mLock) { // Normalize package name to handle renamed packages packageName = normalizePackageNameLPr(packageName); @@ -21810,7 +21359,7 @@ public class PackageManagerService extends IPackageManager.Stub } private List<String> collectAbsoluteCodePaths() { - synchronized (mPackages) { + synchronized (mLock) { List<String> codePaths = new ArrayList<>(); final int packageCount = mSettings.mPackages.size(); for (int i = 0; i < packageCount; i++) { @@ -21961,7 +21510,7 @@ public class PackageManagerService extends IPackageManager.Stub // Ensure that data directories are ready to roll for all packages // installed for this volume and user final List<PackageSetting> packages; - synchronized (mPackages) { + synchronized (mLock) { packages = mSettings.getVolumePackagesLPr(volumeUuid); } int preparedCount = 0; @@ -22003,7 +21552,7 @@ public class PackageManagerService extends IPackageManager.Stub */ private void prepareAppDataAfterInstallLIF(PackageParser.Package pkg) { final PackageSetting ps; - synchronized (mPackages) { + synchronized (mLock) { ps = mSettings.mPackages.get(pkg.packageName); mSettings.writeKernelMappingLPr(ps); } @@ -22065,7 +21614,7 @@ public class PackageManagerService extends IPackageManager.Stub } final PackageSetting ps; - synchronized (mPackages) { + synchronized (mLock) { ps = mSettings.mPackages.get(pkg.packageName); } final String volumeUuid = pkg.volumeUuid; @@ -22126,7 +21675,7 @@ public class PackageManagerService extends IPackageManager.Stub if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { // TODO: mark this structure as dirty so we persist it! - synchronized (mPackages) { + synchronized (mLock) { if (ps != null) { ps.setCeDataInode(ceDataInode, userId); } @@ -22256,7 +21805,7 @@ public class PackageManagerService extends IPackageManager.Stub } public PackageFreezer(String packageName, int userId, String killReason) { - synchronized (mPackages) { + synchronized (mLock) { mPackageName = packageName; mWeFroze = mFrozenPackages.add(mPackageName); @@ -22294,7 +21843,7 @@ public class PackageManagerService extends IPackageManager.Stub public void close() { mCloseGuard.close(); if (mClosed.compareAndSet(false, true)) { - synchronized (mPackages) { + synchronized (mLock) { if (mWeFroze) { mFrozenPackages.remove(mPackageName); } @@ -22313,7 +21862,7 @@ public class PackageManagerService extends IPackageManager.Stub * Verify that given package is currently frozen. */ private void checkPackageFrozen(String packageName) { - synchronized (mPackages) { + synchronized (mLock) { if (!mFrozenPackages.contains(packageName)) { Slog.wtf(TAG, "Expected " + packageName + " to be frozen!", new Throwable()); } @@ -22357,7 +21906,7 @@ public class PackageManagerService extends IPackageManager.Stub final boolean isCurrentLocationExternal; // reader - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package pkg = mPackages.get(packageName); final PackageSetting ps = mSettings.mPackages.get(packageName); if (pkg == null @@ -22570,7 +22119,7 @@ public class PackageManagerService extends IPackageManager.Stub */ private void logAppMovedStorage(String packageName, boolean isPreviousLocationExternal) { final PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); } if (pkg == null) { @@ -22667,7 +22216,7 @@ public class PackageManagerService extends IPackageManager.Stub /** Called by UserManagerService */ void cleanUpUser(UserManagerService userManager, int userHandle) { - synchronized (mPackages) { + synchronized (mLock) { mDirtyUsers.remove(userHandle); mUserNeedsBadging.delete(userHandle); mSettings.removeUserLPw(userHandle); @@ -22682,7 +22231,7 @@ public class PackageManagerService extends IPackageManager.Stub * that are no longer in use by any other user. * @param userHandle the user being removed */ - @GuardedBy("mPackages") + @GuardedBy("mLock") private void removeUnusedPackagesLPw(UserManagerService userManager, final int userHandle) { final boolean DEBUG_CLEAN_APKS = false; int [] users = userManager.getUserIds(); @@ -22733,7 +22282,7 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mInstallLock) { mSettings.createNewUserLI(this, mInstaller, userId, disallowedPackages); } - synchronized (mPackages) { + synchronized (mLock) { scheduleWritePackageRestrictionsLocked(userId); scheduleWritePackageListLocked(userId); primeDomainVerificationsLPw(userId); @@ -22750,7 +22299,7 @@ public class PackageManagerService extends IPackageManager.Stub android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, "Only package verification agents can read the verifier device identity"); - synchronized (mPackages) { + synchronized (mLock) { return mSettings.getVerifierDeviceIdentityLPw(); } } @@ -22812,7 +22361,7 @@ public class PackageManagerService extends IPackageManager.Stub if (packageName == null || alias == null) { return null; } - synchronized(mPackages) { + synchronized (mLock) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); @@ -22833,7 +22382,7 @@ public class PackageManagerService extends IPackageManager.Stub if (packageName == null) { return null; } - synchronized(mPackages) { + synchronized (mLock) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); final PackageParser.Package pkg = mPackages.get(packageName); @@ -22866,7 +22415,7 @@ public class PackageManagerService extends IPackageManager.Stub if (packageName == null || ks == null) { return false; } - synchronized(mPackages) { + synchronized (mLock) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid, @@ -22892,7 +22441,7 @@ public class PackageManagerService extends IPackageManager.Stub if (packageName == null || ks == null) { return false; } - synchronized(mPackages) { + synchronized (mLock) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid, @@ -22909,7 +22458,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private void deletePackageIfUnusedLPr(final String packageName) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps == null) { @@ -23181,7 +22730,7 @@ public class PackageManagerService extends IPackageManager.Stub } private SigningDetails getSigningDetails(@NonNull String packageName) { - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Package p = mPackages.get(packageName); if (p == null) { return null; @@ -23191,7 +22740,7 @@ public class PackageManagerService extends IPackageManager.Stub } private SigningDetails getSigningDetails(int uid) { - synchronized (mPackages) { + synchronized (mLock) { final int appId = UserHandle.getAppId(uid); final Object obj = mSettings.getSettingLPr(appId); if (obj != null) { @@ -23218,7 +22767,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean filterAppAccess(PackageParser.Package pkg, int callingUid, int userId) { - synchronized (mPackages) { + synchronized (mLock) { return PackageManagerService.this .filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid, userId); } @@ -23226,7 +22775,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean filterAppAccess(String packageName, int callingUid, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null) { return false; @@ -23238,7 +22787,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public PackageParser.Package getPackage(String packageName) { - synchronized (mPackages) { + synchronized (mLock) { packageName = resolveInternalPackageNameLPr( packageName, PackageManager.VERSION_CODE_HIGHEST); return mPackages.get(packageName); @@ -23247,7 +22796,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public PackageParser.Package getPackage(int uid) { - synchronized (mPackages) { + synchronized (mLock) { final String[] packageNames = getPackagesForUid(uid); PackageParser.Package pkg = null; final int numPackages = packageNames == null ? 0 : packageNames.length; @@ -23260,7 +22809,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public PackageList getPackageList(PackageListObserver observer) { - synchronized (mPackages) { + synchronized (mLock) { final int N = mPackages.size(); final ArrayList<String> list = new ArrayList<>(N); for (int i = 0; i < N; i++) { @@ -23276,14 +22825,14 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void removePackageListObserver(PackageListObserver observer) { - synchronized (mPackages) { + synchronized (mLock) { mPackageListObservers.remove(observer); } } @Override public PackageParser.Package getDisabledSystemPackage(String packageName) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName); return (ps != null) ? ps.pkg : null; } @@ -23336,7 +22885,7 @@ public class PackageManagerService extends IPackageManager.Stub public void setKeepUninstalledPackages(final List<String> packageList) { Preconditions.checkNotNull(packageList); List<String> removedFromList = null; - synchronized (mPackages) { + synchronized (mLock) { if (mKeepUninstalledPackages != null) { final int packagesCount = mKeepUninstalledPackages.size(); for (int i = 0; i < packagesCount; i++) { @@ -23362,7 +22911,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isPermissionsReviewRequired(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null) { return false; @@ -23382,7 +22931,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public Bundle getSuspendedPackageLauncherExtras(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); PersistableBundle launcherExtras = null; if (ps != null) { @@ -23394,7 +22943,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isPackageSuspended(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); return (ps != null) ? ps.getSuspended(userId) : false; } @@ -23402,7 +22951,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public String getSuspendingPackage(String suspendedPackage, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(suspendedPackage); return (ps != null) ? ps.readUserState(userId).suspendingPackage : null; } @@ -23410,7 +22959,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(suspendedPackage); return (ps != null) ? ps.readUserState(userId).dialogInfo : null; } @@ -23418,7 +22967,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public int getDistractingPackageRestrictions(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); return (ps != null) ? ps.getDistractionFlags(userId) : RESTRICTION_NONE; } @@ -23505,7 +23054,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isPackageEphemeral(int userId, String packageName) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); return ps != null ? ps.getInstantApp(userId) : false; } @@ -23513,21 +23062,21 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean wasPackageEverLaunched(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { return mSettings.wasPackageEverLaunchedLPr(packageName, userId); } } @Override public boolean isEnabledAndMatches(ComponentInfo info, int flags, int userId) { - synchronized (mPackages) { + synchronized (mLock) { return mSettings.isEnabledAndMatchLPr(info, flags, userId); } } @Override public boolean userNeedsBadging(int userId) { - synchronized (mPackages) { + synchronized (mLock) { return PackageManagerService.this.userNeedsBadging(userId); } } @@ -23549,7 +23098,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void grantEphemeralAccess(int userId, Intent intent, int targetAppId, int ephemeralAppId) { - synchronized (mPackages) { + synchronized (mLock) { mInstantAppRegistry.grantInstantAccessLPw(userId, intent, targetAppId, ephemeralAppId); } @@ -23557,7 +23106,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isInstantAppInstallerComponent(ComponentName component) { - synchronized (mPackages) { + synchronized (mLock) { return mInstantAppInstallerActivity != null && mInstantAppInstallerActivity.getComponentName().equals(component); } @@ -23581,7 +23130,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isPackagePersistent(String packageName) { - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Package pkg = mPackages.get(packageName); return pkg != null ? ((pkg.applicationInfo.flags&(ApplicationInfo.FLAG_SYSTEM @@ -23593,7 +23142,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isLegacySystemApp(PackageParser.Package pkg) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = (PackageSetting) pkg.mExtras; return mPromoteSystemApps && ps.isSystem() @@ -23604,7 +23153,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public List<PackageInfo> getOverlayPackages(int userId) { final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>(); - synchronized (mPackages) { + synchronized (mLock) { for (PackageParser.Package p : mPackages.values()) { if (p.mOverlayTarget != null) { PackageInfo pkg = generatePackageInfo((PackageSetting)p.mExtras, 0, userId); @@ -23620,7 +23169,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public List<String> getTargetPackageNames(int userId) { List<String> targetPackages = new ArrayList<>(); - synchronized (mPackages) { + synchronized (mLock) { for (PackageParser.Package p : mPackages.values()) { if (p.mOverlayTarget == null) { targetPackages.add(p.packageName); @@ -23633,7 +23182,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean setEnabledOverlayPackages(int userId, @NonNull String targetPackageName, @Nullable List<String> overlayPackageNames) { - synchronized (mPackages) { + synchronized (mLock) { if (targetPackageName == null || mPackages.get(targetPackageName) == null) { Slog.e(TAG, "failed to find package " + targetPackageName); return false; @@ -23680,28 +23229,28 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void addIsolatedUid(int isolatedUid, int ownerUid) { - synchronized (mPackages) { + synchronized (mLock) { mIsolatedOwners.put(isolatedUid, ownerUid); } } @Override public void removeIsolatedUid(int isolatedUid) { - synchronized (mPackages) { + synchronized (mLock) { mIsolatedOwners.delete(isolatedUid); } } @Override public int getUidTargetSdkVersion(int uid) { - synchronized (mPackages) { + synchronized (mLock) { return getUidTargetSdkVersionLockedLPr(uid); } } @Override public int getPackageTargetSdkVersion(String packageName) { - synchronized (mPackages) { + synchronized (mLock) { return getPackageTargetSdkVersionLockedLPr(packageName); } } @@ -23713,7 +23262,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean canAccessComponent(int callingUid, ComponentName component, int userId) { - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); return ps != null && !PackageManagerService.this.filterAppAccessLPr( ps, callingUid, component, TYPE_UNKNOWN, userId); @@ -23722,35 +23271,35 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean hasInstantApplicationMetadata(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { return mInstantAppRegistry.hasInstantApplicationMetadataLPr(packageName, userId); } } @Override public void notifyPackageUse(String packageName, int reason) { - synchronized (mPackages) { + synchronized (mLock) { PackageManagerService.this.notifyPackageUseLocked(packageName, reason); } } @Override public SparseArray<String> getAppsWithSharedUserIds() { - synchronized (mPackages) { + synchronized (mLock) { return getAppsWithSharedUserIdsLocked(); } } @Override public String getSharedUserIdForPackage(String packageName) { - synchronized (mPackages) { + synchronized (mLock) { return getSharedUserIdForPackageLocked(packageName); } } @Override public String[] getPackagesForSharedUserId(String sharedUserId, int userId) { - synchronized (mPackages) { + synchronized (mLock) { return getPackagesForSharedUserIdLocked(sharedUserId, userId); } } @@ -23779,7 +23328,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ArraySet<String> getEnabledComponents(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { PackageSetting setting = mSettings.getPackageLPr(packageName); if (setting == null) { return new ArraySet<>(); @@ -23790,7 +23339,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public ArraySet<String> getDisabledComponents(String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { PackageSetting setting = mSettings.getPackageLPr(packageName); if (setting == null) { return new ArraySet<>(); @@ -23802,7 +23351,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public @PackageManager.EnabledState int getApplicationEnabledState( String packageName, int userId) { - synchronized (mPackages) { + synchronized (mLock) { PackageSetting setting = mSettings.getPackageLPr(packageName); if (setting == null) { return COMPONENT_ENABLED_STATE_DEFAULT; @@ -23822,7 +23371,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean compileLayouts(String packageName) { PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { return false; @@ -23839,7 +23388,7 @@ public class PackageManagerService extends IPackageManager.Stub @Nullable @Override public String removeLegacyDefaultBrowserPackageName(int userId) { - synchronized (mPackages) { + synchronized (mLock) { return mSettings.removeDefaultBrowserPackageNameLPw(userId); } } @@ -23892,7 +23441,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void setRuntimePermissionsFingerPrint(@NonNull String fingerPrint, @UserIdInt int userId) { - synchronized (mPackages) { + synchronized (mLock) { mSettings.setRuntimePermissionsFingerPrintLPr(fingerPrint, userId); } } @@ -23908,7 +23457,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void writeSettings(boolean async) { - synchronized (mPackages) { + synchronized (mLock) { if (async) { scheduleWriteSettingsLocked(); } else { @@ -23919,7 +23468,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void writePermissionSettings(int[] userIds, boolean async) { - synchronized (mPackages) { + synchronized (mLock) { for (int userId : userIds) { mSettings.writeRuntimePermissionsForUserLPr(userId, !async); } @@ -23930,7 +23479,7 @@ public class PackageManagerService extends IPackageManager.Stub public int getTargetSdk(int uid) { int userId = UserHandle.getUserId(uid); - synchronized (mPackages) { + synchronized (mLock) { final Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid)); if (obj instanceof PackageSetting) { final PackageSetting ps = (PackageSetting) obj; @@ -23961,7 +23510,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isCallerInstallerOfRecord( @NonNull PackageParser.Package pkg, int callingUid) { - synchronized (mPackages) { + synchronized (mLock) { if (pkg == null) { return false; } @@ -23978,14 +23527,14 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean areDefaultRuntimePermissionsGranted(int userId) { - synchronized (mPackages) { + synchronized (mLock) { return mSettings.areDefaultRuntimePermissionsGrantedLPr(userId); } } @Override public void setReadExternalStorageEnforced(boolean enforced) { - synchronized (mPackages) { + synchronized (mLock) { if (mSettings.mReadExternalStorageEnforced != null && mSettings.mReadExternalStorageEnforced == enforced) { return; @@ -23996,10 +23545,10 @@ public class PackageManagerService extends IPackageManager.Stub } } - @GuardedBy("mPackages") + @GuardedBy("mLock") private SparseArray<String> getAppsWithSharedUserIdsLocked() { final SparseArray<String> sharedUserIds = new SparseArray<>(); - synchronized (mPackages) { + synchronized (mLock) { for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) { sharedUserIds.put(UserHandle.getAppId(setting.userId), setting.name); } @@ -24007,13 +23556,13 @@ public class PackageManagerService extends IPackageManager.Stub return sharedUserIds; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private String getSharedUserIdForPackageLocked(String packageName) { final PackageSetting ps = mSettings.mPackages.get(packageName); return (ps != null && ps.isSharedUser()) ? ps.sharedUser.name : null; } - @GuardedBy("mPackages") + @GuardedBy("mLock") private String[] getPackagesForSharedUserIdLocked(String sharedUserId, int userId) { try { final SharedUserSetting sus = mSettings.getSharedUserLPw( @@ -24045,7 +23594,7 @@ public class PackageManagerService extends IPackageManager.Stub mContext.enforceCallingOrSelfPermission( Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, "setRuntimePermissionVersion"); - synchronized (mPackages) { + synchronized (mLock) { return mSettings.getDefaultRuntimePermissionsVersionLPr(userId); } } @@ -24057,13 +23606,13 @@ public class PackageManagerService extends IPackageManager.Stub mContext.enforceCallingOrSelfPermission( Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, "setRuntimePermissionVersion"); - synchronized (mPackages) { + synchronized (mLock) { mSettings.setDefaultRuntimePermissionsVersionLPr(version, userId); } } void forEachPackage(Consumer<PackageParser.Package> actionLocked) { - synchronized (mPackages) { + synchronized (mLock) { int numPackages = mPackages.size(); for (int i = 0; i < numPackages; i++) { actionLocked.accept(mPackages.valueAt(i)); @@ -24073,7 +23622,7 @@ public class PackageManagerService extends IPackageManager.Stub void forEachInstalledPackage(@NonNull Consumer<PackageParser.Package> actionLocked, @UserIdInt int userId) { - synchronized (mPackages) { + synchronized (mLock) { int numPackages = mPackages.size(); for (int i = 0; i < numPackages; i++) { PackageParser.Package pkg = mPackages.valueAt(i); @@ -24095,7 +23644,7 @@ public class PackageManagerService extends IPackageManager.Stub * @return A copy of the values of mPackages. */ Collection<PackageParser.Package> getPackages() { - synchronized (mPackages) { + synchronized (mLock) { return new ArrayList<>(mPackages.values()); } } @@ -24148,7 +23697,7 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */, false /* checkShell */, "get install reason"); - synchronized (mPackages) { + synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); if (filterAppAccessLPr(ps, callingUid, userId)) { return PackageManager.INSTALL_REASON_UNKNOWN; @@ -24234,13 +23783,13 @@ public class PackageManagerService extends IPackageManager.Stub if (!isInstantApp(packageName, userId)) { return null; } - synchronized (mPackages) { + synchronized (mLock) { return mInstantAppRegistry.getInstantAppAndroidIdLPw(packageName, userId); } } boolean canHaveOatDir(String packageName) { - synchronized (mPackages) { + synchronized (mLock) { PackageParser.Package p = mPackages.get(packageName); if (p == null) { return false; @@ -24265,7 +23814,7 @@ public class PackageManagerService extends IPackageManager.Stub final List<String> codePaths; final String oatDir; final PackageParser.Package pkg; - synchronized (mPackages) { + synchronized (mLock) { pkg = mPackages.get(packageName); } instructionSets = getAppDexInstructionSets(pkg.applicationInfo); @@ -24286,7 +23835,7 @@ public class PackageManagerService extends IPackageManager.Stub Set<String> getUnusedPackages(long downgradeTimeThresholdMillis) { Set<String> unusedPackages = new HashSet<>(); long currentTimeInMillis = System.currentTimeMillis(); - synchronized (mPackages) { + synchronized (mLock) { for (PackageParser.Package pkg : mPackages.values()) { PackageSetting ps = mSettings.mPackages.get(pkg.packageName); if (ps == null) { @@ -24321,7 +23870,7 @@ public class PackageManagerService extends IPackageManager.Stub + SET_HARMFUL_APP_WARNINGS + " permission."); } - synchronized(mPackages) { + synchronized (mLock) { mSettings.setHarmfulAppWarningLPw(packageName, warning, userId); scheduleWritePackageRestrictionsLocked(userId); } @@ -24342,7 +23891,7 @@ public class PackageManagerService extends IPackageManager.Stub + SET_HARMFUL_APP_WARNINGS + " permission."); } - synchronized(mPackages) { + synchronized (mLock) { return mSettings.getHarmfulAppWarningLPr(packageName, userId); } } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 58f262c4c889..029673ffd87b 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -270,7 +270,8 @@ public abstract class PackageSettingBase extends SettingBase { updateAvailable = orig.updateAvailable; } - private PackageUserState modifyUserState(int userId) { + @VisibleForTesting + PackageUserState modifyUserState(int userId) { PackageUserState state = mUserState.get(userId); if (state == null) { state = new PackageUserState(); @@ -463,6 +464,18 @@ public abstract class PackageSettingBase extends SettingBase { state.harmfulAppWarning = harmfulAppWarning; } + void setUserState(int userId, PackageUserState otherState) { + setUserState(userId, otherState.ceDataInode, otherState.enabled, otherState.installed, + otherState.stopped, otherState.notLaunched, otherState.hidden, + otherState.distractionFlags, otherState.suspended, otherState.suspendingPackage, + otherState.dialogInfo, otherState.suspendedAppExtras, + otherState.suspendedLauncherExtras, otherState.instantApp, + otherState.virtualPreload, otherState.lastDisableAppCaller, + otherState.enabledComponents, otherState.disabledComponents, + otherState.domainVerificationStatus, otherState.appLinkGeneration, + otherState.installReason, otherState.harmfulAppWarning); + } + ArraySet<String> getEnabledComponents(int userId) { return readUserState(userId).enabledComponents; } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 3bc2236a8221..c1cb53d4ff0f 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -4020,7 +4020,7 @@ public final class Settings { String[] seinfos; int[] targetSdkVersions; int packagesCount; - synchronized (mPackages) { + synchronized (mLock) { Collection<PackageSetting> packages = mPackages.values(); packagesCount = packages.size(); volumeUuids = new String[packagesCount]; @@ -4064,7 +4064,7 @@ public final class Settings { Slog.w(TAG, "Failed to prepare app data", e); } } - synchronized (mPackages) { + synchronized (mLock) { applyDefaultPreferredAppsLPw(userHandle); } } diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 2d8a2acd575f..ebba128b5f28 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -79,7 +79,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManagerInternal; import android.text.TextUtils; -import android.text.format.Time; +import android.text.format.TimeMigrationUtils; import android.util.ArraySet; import android.util.AtomicFile; import android.util.KeyValueListParser; @@ -3981,9 +3981,7 @@ public class ShortcutService extends IShortcutService.Stub { } static String formatTime(long time) { - Time tobj = new Time(); - tobj.set(time); - return tobj.format("%Y-%m-%d %H:%M:%S"); + return TimeMigrationUtils.formatMillisWithFixedFormat(time); } private void dumpCurrentTime(PrintWriter pw) { diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index bf141a0f139b..bdeaf028bac8 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -180,6 +180,8 @@ public class StagingManager { checkDowngrade(session, activePackage, pkg); result.add(pkg); } + Slog.d(TAG, "Session " + session.sessionId + " has following APEX packages: [" + + result.stream().map(p -> p.packageName).collect(Collectors.joining(",")) + "]"); return result; } @@ -206,7 +208,7 @@ public class StagingManager { throws PackageManagerException { final long activeVersion = activePackage.applicationInfo.longVersionCode; final long newVersionCode = newPackage.applicationInfo.longVersionCode; - boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted( + final boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted( session.params.installFlags, activePackage.applicationInfo.flags); if (activeVersion > newVersionCode && !allowsDowngrade) { if (!mApexManager.abortActiveSession()) { @@ -225,6 +227,7 @@ public class StagingManager { } private void preRebootVerification(@NonNull PackageInstallerSession session) { + Slog.d(TAG, "Starting preRebootVerification for session " + session.sessionId); final boolean hasApex = sessionContainsApex(session); // APEX checks. For single-package sessions, check if they contain an APEX. For // multi-package sessions, find all the child sessions that contain an APEX. @@ -243,6 +246,8 @@ public class StagingManager { if (sessionContainsApk(session)) { try { + Slog.d(TAG, "Running a pre-reboot verification for APKs in session " + + session.sessionId + " by performing a dry-run install"); installApksInSession(session, /* preReboot */ true); // TODO(b/118865310): abort the session on apexd. } catch (PackageManagerException e) { @@ -277,6 +282,7 @@ public class StagingManager { // On the other hand, if the order of the calls was inverted (first call apexd, then mark // session as ready), then if a device gets rebooted right after the call to apexd, only // apex part of the train will be applied, leaving device in an inconsistent state. + Slog.d(TAG, "Marking session " + session.sessionId + " as ready"); session.setStagedSessionReady(); if (!hasApex) { // Session doesn't contain apex, nothing to do. @@ -315,6 +321,7 @@ public class StagingManager { } private void resumeSession(@NonNull PackageInstallerSession session) { + Slog.d(TAG, "Resuming session " + session.sessionId); final boolean hasApex = sessionContainsApex(session); if (hasApex) { // Check with apexservice whether the apex packages have been activated. @@ -348,9 +355,12 @@ public class StagingManager { + "retry at next reboot."); return; } + Slog.i(TAG, "APEX packages in session " + session.sessionId + + " were successfully activated. Proceeding with APK packages, if any"); } // The APEX part of the session is activated, proceed with the installation of APKs. try { + Slog.d(TAG, "Installing APK packages in session " + session.sessionId); installApksInSession(session, /* preReboot */ false); } catch (PackageManagerException e) { session.setStagedSessionFailed(e.error, e.getMessage()); @@ -370,6 +380,7 @@ public class StagingManager { return; } + Slog.d(TAG, "Marking session " + session.sessionId + " as applied"); session.setStagedSessionApplied(); if (hasApex) { mApexManager.markStagedSessionSuccessful(session.sessionId); diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING index b829f0b53086..f7b60c25ce4a 100644 --- a/services/core/java/com/android/server/pm/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/TEST_MAPPING @@ -8,6 +8,20 @@ }, { "name": "CtsCompilationTestCases" + }, + { + "name": "FrameworksServicesTests", + "options": [ + { + "include-filter": "com.android.server.pm." + }, + { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + } + ] } ], "postsubmit": [ diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 673ab6c5f095..674e8921ff05 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -54,6 +54,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.app.AppOpsManager; import android.app.ApplicationPackageManager; import android.app.IActivityManager; import android.content.Context; @@ -1447,10 +1448,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { /** * Reverts user permission state changes (permissions and flags). * - * @param ps The package for which to reset. + * @param pkg The package for which to reset. * @param userId The device user for which to do a reset. */ - @GuardedBy("mPackages") + @GuardedBy("mLock") private void resetRuntimePermissionsInternal(final PackageParser.Package pkg, final int userId) { final String packageName = pkg.packageName; @@ -1521,6 +1522,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } }; + final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); for (int i = 0; i < permissionCount; i++) { final String permName = pkg.requestedPermissions.get(i); final BasePermission bp; @@ -1588,6 +1590,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0) { grantRuntimePermissionInternal(permName, packageName, false, Process.SYSTEM_UID, userId, delayingPermCallback); + // Allow app op later as we are holding mPackages + // PermissionPolicyService will handle the app op for foreground/background + // permissions. + String appOp = AppOpsManager.permissionToOp(permName); + if (appOp != null) { + mHandler.post(() -> appOpsManager.setUidMode(appOp, uid, + AppOpsManager.MODE_ALLOWED)); + } // If permission review is enabled the permissions for a legacy apps // are represented as constantly granted runtime ones, so don't revoke. } else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) { diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java index e139ab86775d..4970862070bb 100644 --- a/services/core/java/com/android/server/slice/PinnedSliceState.java +++ b/services/core/java/com/android/server/slice/PinnedSliceState.java @@ -188,7 +188,7 @@ public class PinnedSliceState { b.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri); try { client.call(SliceProvider.METHOD_PIN, null, b); - } catch (RemoteException e) { + } catch (Exception e) { Log.w(TAG, "Unable to contact " + mUri, e); } } @@ -201,7 +201,7 @@ public class PinnedSliceState { b.putParcelable(SliceProvider.EXTRA_BIND_URI, mUri); try { client.call(SliceProvider.METHOD_UNPIN, null, b); - } catch (RemoteException e) { + } catch (Exception e) { Log.w(TAG, "Unable to contact " + mUri, e); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 26b1f7b49aae..015464e94ffc 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -163,6 +163,7 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; @@ -1630,22 +1631,52 @@ final class ActivityRecord extends ConfigurationContainer { setSavedState(null /* savedState */); } + /** Activity finish request was not executed. */ + static final int FINISH_RESULT_CANCELLED = 0; + /** Activity finish was requested, activity will be fully removed later. */ + static final int FINISH_RESULT_REQUESTED = 1; + /** Activity finish was requested, activity was removed from history. */ + static final int FINISH_RESULT_REMOVED = 2; + + /** Definition of possible results for activity finish request. */ + @IntDef(prefix = { "FINISH_RESULT_" }, value = { + FINISH_RESULT_CANCELLED, + FINISH_RESULT_REQUESTED, + FINISH_RESULT_REMOVED, + }) + @interface FinishRequest {} + /** * See {@link #finishActivityLocked(int, Intent, String, boolean, boolean)} */ - boolean finishActivityLocked(int resultCode, Intent resultData, String reason, boolean oomAdj) { + @FinishRequest int finishActivityLocked(int resultCode, Intent resultData, String reason, + boolean oomAdj) { return finishActivityLocked(resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY); } /** - * @return Returns true if this activity has been removed from the history - * list, or false if it is still in the list and will be removed later. + * @return One of {@link FinishRequest} values: + * {@link #FINISH_RESULT_REMOVED} if this activity has been removed from the history list. + * {@link #FINISH_RESULT_REQUESTED} if removal process was started, but it is still in the list + * and will be removed from history later. + * {@link #FINISH_RESULT_CANCELLED} if activity is already finishing or in invalid state and the + * request to finish it was not ignored. */ - boolean finishActivityLocked(int resultCode, Intent resultData, String reason, boolean oomAdj, - boolean pauseImmediately) { + @FinishRequest int finishActivityLocked(int resultCode, Intent resultData, String reason, + boolean oomAdj, boolean pauseImmediately) { + if (DEBUG_RESULTS || DEBUG_STATES) { + Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode + + ", data=" + resultData + ", reason=" + reason); + } + if (finishing) { - Slog.w(TAG, "Duplicate finish request for " + this); - return false; + Slog.w(TAG, "Duplicate finish request for r=" + this); + return FINISH_RESULT_CANCELLED; + } + + if (!isInStackLocked()) { + Slog.w(TAG, "Finish request when not in stack for r=" + this); + return FINISH_RESULT_CANCELLED; } mAtmService.mWindowManager.deferSurfaceLayout(); @@ -1737,12 +1768,12 @@ final class ActivityRecord extends ConfigurationContainer { taskOverlay.prepareActivityHideTransitionAnimation(transit); } } - return removedActivity; + return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED; } else { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this); } - return false; + return FINISH_RESULT_REQUESTED; } finally { mAtmService.mWindowManager.continueSurfaceLayout(); } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 81d8fa9554bc..17536e42acc8 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -58,6 +58,8 @@ import static com.android.server.wm.ActivityDisplay.POSITION_BOTTOM; import static com.android.server.wm.ActivityDisplay.POSITION_TOP; import static com.android.server.wm.ActivityRecord.FINISH_AFTER_VISIBLE; import static com.android.server.wm.ActivityRecord.FINISH_IMMEDIATELY; +import static com.android.server.wm.ActivityRecord.FINISH_RESULT_CANCELLED; +import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED; import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; @@ -1153,13 +1155,6 @@ class ActivityStack extends ConfigurationContainer { return null; } - private TaskRecord bottomTask() { - if (mTaskHistory.isEmpty()) { - return null; - } - return mTaskHistory.get(0); - } - TaskRecord taskForIdLocked(int id) { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); @@ -2787,8 +2782,8 @@ class ActivityStack extends ConfigurationContainer { !mLastNoHistoryActivity.finishing) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + mLastNoHistoryActivity + " on new resume"); - requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, - null, "resume-no-history", false); + mLastNoHistoryActivity.finishActivityLocked(Activity.RESULT_CANCELED, + null /* resultData */, "resume-no-history", false /* oomAdj */); mLastNoHistoryActivity = null; } @@ -3023,8 +3018,8 @@ class ActivityStack extends ConfigurationContainer { // If any exception gets thrown, toss away this // activity and try the next one. Slog.w(TAG, "Exception thrown during resume of " + next, e); - requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, - "resume-exception", true); + next.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */, + "resume-exception", true /* oomAdj */); return true; } } else { @@ -3452,7 +3447,7 @@ class ActivityStack extends ConfigurationContainer { if (DEBUG_TASKS) Slog.w(TAG_TASKS, "resetTaskIntendedTask: calling finishActivity on " + p); if (p.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */, - "reset-task", false /* oomAdj */)) { + "reset-task", false /* oomAdj */) == FINISH_RESULT_REMOVED) { end--; srcPos--; } @@ -3760,10 +3755,9 @@ class ActivityStack extends ConfigurationContainer { if (!r.finishing) { if (!shouldSleepActivities()) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); - if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, - "stop-no-history", false)) { - // If {@link requestFinishActivityLocked} returns {@code true}, - // {@link adjustFocusedActivityStack} would have been already called. + if (r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */, + "stop-no-history", false /* oomAdj */) != FINISH_RESULT_CANCELLED) { + // {@link adjustFocusedActivityStack} must have been already called. r.resumeKeyDispatchingLocked(); return; } @@ -3812,25 +3806,7 @@ class ActivityStack extends ConfigurationContainer { } } - /** - * @return Returns true if the activity is being finished, false if for - * some reason it is being left as-is. - */ - final boolean requestFinishActivityLocked(IBinder token, int resultCode, - Intent resultData, String reason, boolean oomAdj) { - ActivityRecord r = isInStackLocked(token); - if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES, - "Finishing activity token=" + token + " r=" - + ", result=" + resultCode + ", data=" + resultData - + ", reason=" + reason); - if (r == null) { - return false; - } - - r.finishActivityLocked(resultCode, resultData, reason, oomAdj); - return true; - } - + /** Finish all activities that were started for result from the specified activity. */ final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; @@ -4052,8 +4028,8 @@ class ActivityStack extends ConfigurationContainer { } final long origId = Binder.clearCallingIdentity(); for (int i = start; i > finishTo; i--) { - ActivityRecord r = activities.get(i); - requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true); + final ActivityRecord r = activities.get(i); + r.finishActivityLocked(resultCode, resultData, "navigate-up", true /* oomAdj */); // Only return the supplied result for the first activity finished resultCode = Activity.RESULT_CANCELED; resultData = null; @@ -4090,8 +4066,8 @@ class ActivityStack extends ConfigurationContainer { } catch (RemoteException e) { foundParentInTask = false; } - requestFinishActivityLocked(parent.appToken, resultCode, - resultData, "navigate-top", true); + parent.finishActivityLocked(resultCode, resultData, "navigate-top", + true /* oomAdj */); } } Binder.restoreCallingIdentity(origId); diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index e49e991c2825..1c56a107ab9e 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -890,8 +890,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); proc.appDied(); - stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, - "2nd-crash", false); + r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */, + "2nd-crash", false /* oomAdj */); return false; } @@ -1191,8 +1191,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { final PackageInfo packageInfo; try { packageInfo = mService.mContext.getPackageManager() - .getPackageInfoAsUser(callingPackage, PackageManager.GET_PERMISSIONS, - UserHandle.getUserId(callingUid)); + .getPackageInfo(callingPackage, PackageManager.GET_PERMISSIONS); } catch (PackageManager.NameNotFoundException e) { Slog.i(TAG, "Cannot find package info for " + callingPackage); return ACTIVITY_RESTRICTION_NONE; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index fb393e60f93e..b351faf7e9f1 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -84,6 +84,7 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PRE import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES; import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE; import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE; +import static com.android.server.wm.ActivityRecord.FINISH_RESULT_CANCELLED; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; @@ -1011,7 +1012,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public final int startActivities(IApplicationThread caller, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions, int userId) { - assertPackageMatchesCallingUid(callingPackage); final String reason = "startActivities"; enforceNotIsolatedCaller(reason); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, reason); @@ -1031,11 +1031,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { true /*validateIncomingUser*/); } - private int startActivityAsUser(IApplicationThread caller, String callingPackage, + int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) { - assertPackageMatchesCallingUid(callingPackage); enforceNotIsolatedCaller("startActivityAsUser"); userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser, @@ -1208,7 +1207,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public final WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { - assertPackageMatchesCallingUid(callingPackage); final WaitResult res = new WaitResult(); synchronized (mGlobalLock) { enforceNotIsolatedCaller("startActivityAndWait"); @@ -1236,7 +1234,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public final int startActivityWithConfig(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, Configuration config, Bundle bOptions, int userId) { - assertPackageMatchesCallingUid(callingPackage); synchronized (mGlobalLock) { enforceNotIsolatedCaller("startActivityWithConfig"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, @@ -1286,7 +1283,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, IBinder permissionToken, boolean ignoreTargetSecurity, int userId) { - assertPackageMatchesCallingUid(callingPackage); // This is very dangerous -- it allows you to perform a start activity (including // permission grants) as any app that may launch one of your own activities. So we only // allow this in two cases: @@ -1416,7 +1412,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Intent intent, String resolvedType, IVoiceInteractionSession session, IVoiceInteractor interactor, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { - assertPackageMatchesCallingUid(callingPackage); mAmInternal.enforceCallingPermission(BIND_VOICE_INTERACTION, "startVoiceActivity()"); if (session == null || interactor == null) { throw new NullPointerException("null session or interactor"); @@ -1440,7 +1435,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public int startAssistantActivity(String callingPackage, int callingPid, int callingUid, Intent intent, String resolvedType, Bundle bOptions, int userId) { - assertPackageMatchesCallingUid(callingPackage); mAmInternal.enforceCallingPermission(BIND_VOICE_INTERACTION, "startAssistantActivity()"); userId = handleIncomingUser(callingPid, callingUid, userId, "startAssistantActivity"); @@ -1560,13 +1554,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); + final ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r == null) { return true; } // Keep track of the root activity of the task before we finish it final TaskRecord tr = r.getTaskRecord(); - ActivityRecord rootR = tr.getRootActivity(); + final ActivityRecord rootR = tr.getRootActivity(); if (rootR == null) { Slog.w(TAG, "Finishing task with all activities already finished"); } @@ -1616,7 +1610,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // because we don't support returning them across task boundaries. Also, to // keep backwards compatibility we remove the task from recents when finishing // task with root activity. - res = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, + res = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false /* killProcess */, finishWithRootActivity, "finish-activity"); if (!res) { Slog.i(TAG, "Removing task failed to finish activity"); @@ -1624,8 +1618,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Explicitly dismissing the activity so reset its relaunch flag. r.mRelaunchReason = RELAUNCH_REASON_NONE; } else { - res = tr.getStack().requestFinishActivityLocked(token, resultCode, - resultData, "app-request", true); + res = r.finishActivityLocked(resultCode, resultData, "app-request", + true /* oomAdj */) != FINISH_RESULT_CANCELLED; if (!res) { Slog.i(TAG, "Failed to finish by app-request"); } @@ -1649,7 +1643,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps // can finish. - final TaskRecord task = r.getTaskRecord(); if (getLockTaskController().activityBlockedFromFinish(r)) { return false; } @@ -2367,9 +2360,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { void moveTaskToFrontLocked(@Nullable IApplicationThread appThread, @Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options, boolean fromRecents) { + final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); - assertPackageMatchesCallingUid(callingPackage); + if (!isSameApp(callingUid, callingPackage)) { + String msg = "Permission Denial: moveTaskToFrontLocked() from pid=" + + Binder.getCallingPid() + " as package " + callingPackage; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } if (!checkAppSwitchAllowedLocked(callingPid, callingUid, -1, -1, "Task to front")) { SafeActivityOptions.abort(options); return; @@ -2421,7 +2420,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { /** * Return true if callingUid is system, or packageName belongs to that callingUid. */ - private boolean isSameApp(int callingUid, @Nullable String packageName) { + boolean isSameApp(int callingUid, @Nullable String packageName) { try { if (callingUid != 0 && callingUid != SYSTEM_UID) { if (packageName == null) { @@ -2438,21 +2437,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return true; } - /** - * Checks that the provided package name matches the current calling UID, throws a security - * exception if it doesn't. - */ - void assertPackageMatchesCallingUid(@Nullable String packageName) { - final int callingUid = Binder.getCallingUid(); - if (isSameApp(callingUid, packageName)) { - return; - } - final String msg = "Permission Denial: package=" + packageName - + " does not belong to uid=" + callingUid; - Slog.w(TAG, msg); - throw new SecurityException(msg); - } - boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid, int callingPid, int callingUid, String name) { if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) { @@ -2986,7 +2970,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public List<IBinder> getAppTasks(String callingPackage) { int callingUid = Binder.getCallingUid(); - assertPackageMatchesCallingUid(callingPackage); long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { @@ -6093,7 +6076,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { - assertPackageMatchesCallingUid(callingPackage); synchronized (mGlobalLock) { return getActivityStartController().startActivitiesInPackage(uid, realCallingPid, realCallingUid, callingPackage, intents, resolvedTypes, resultTo, options, @@ -6109,7 +6091,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { int userId, TaskRecord inTask, String reason, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { - assertPackageMatchesCallingUid(callingPackage); synchronized (mGlobalLock) { return getActivityStartController().startActivityInPackage(uid, realCallingPid, realCallingUid, callingPackage, intent, resolvedType, resultTo, resultWho, diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java index a8f7768efc87..1eb7455135c7 100644 --- a/services/core/java/com/android/server/wm/AppTaskImpl.java +++ b/services/core/java/com/android/server/wm/AppTaskImpl.java @@ -27,6 +27,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.UserHandle; +import android.util.Slog; /** * An implementation of IAppTask, that allows an app to manage its own tasks via @@ -96,7 +97,12 @@ class AppTaskImpl extends IAppTask.Stub { // Will bring task to front if it already has a root activity. final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); - mService.assertPackageMatchesCallingUid(callingPackage); + if (!mService.isSameApp(callingUid, callingPackage)) { + String msg = "Permission Denial: moveToFront() from pid=" + + Binder.getCallingPid() + " as package " + callingPackage; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } final long origId = Binder.clearCallingIdentity(); try { synchronized (mService.mGlobalLock) { @@ -128,7 +134,6 @@ class AppTaskImpl extends IAppTask.Stub { public int startActivity(IBinder whoThread, String callingPackage, Intent intent, String resolvedType, Bundle bOptions) { checkCaller(); - mService.assertPackageMatchesCallingUid(callingPackage); int callingUser = UserHandle.getCallingUserId(); TaskRecord tr; diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index d15081ca2665..aefc152cb286 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -1015,6 +1015,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree void notifyAppStopped() { if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this); mAppStopped = true; + // Reset the last saved PiP snap fraction on app stop. + mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this); destroySurfaces(); // Remove any starting window that was added for this app if they are still around. removeStartingWindow(); @@ -2485,7 +2487,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // transformed the task. final RecentsAnimationController controller = mWmService.getRecentsAnimationController(); if (controller != null && controller.isAnimatingTask(getTask()) - && controller.shouldCancelWithDeferredScreenshot()) { + && controller.shouldDeferCancelUntilNextTransition()) { return false; } @@ -3076,11 +3078,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree @Override void setHidden(boolean hidden) { super.setHidden(hidden); - - if (hidden) { - // Once the app window is hidden, reset the last saved PiP snap fraction - mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this); - } scheduleAnimation(); } diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index a46fa13adf4e..207e8ef728eb 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -30,6 +30,7 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.app.WindowConfiguration; import android.os.Environment; +import android.os.FileUtils; import android.provider.Settings; import android.util.AtomicFile; import android.util.Slog; @@ -64,6 +65,11 @@ import java.util.HashMap; class DisplayWindowSettings { private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM; + private static final String SYSTEM_DIRECTORY = "system"; + private static final String DISPLAY_SETTINGS_FILE_NAME = "display_settings.xml"; + private static final String VENDOR_DISPLAY_SETTINGS_PATH = "etc/" + DISPLAY_SETTINGS_FILE_NAME; + private static final String WM_DISPLAY_COMMIT_TAG = "wm-displays"; + private static final int IDENTIFIER_UNIQUE_ID = 0; private static final int IDENTIFIER_PORT = 1; @IntDef(prefix = { "IDENTIFIER_" }, value = { @@ -688,8 +694,26 @@ class DisplayWindowSettings { private final AtomicFile mAtomicFile; AtomicFileStorage() { - final File folder = new File(Environment.getDataDirectory(), "system"); - mAtomicFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays"); + final File folder = new File(Environment.getDataDirectory(), SYSTEM_DIRECTORY); + final File settingsFile = new File(folder, DISPLAY_SETTINGS_FILE_NAME); + // If display_settings.xml doesn't exist, try to copy the vendor's one instead + // in order to provide the vendor specific initialization. + if (!settingsFile.exists()) { + copyVendorSettings(settingsFile); + } + mAtomicFile = new AtomicFile(settingsFile, WM_DISPLAY_COMMIT_TAG); + } + + private static void copyVendorSettings(File target) { + final File vendorFile = new File(Environment.getVendorDirectory(), + VENDOR_DISPLAY_SETTINGS_PATH); + if (vendorFile.canRead()) { + try { + FileUtils.copy(vendorFile, target); + } catch (IOException e) { + Slog.e(TAG, "Failed to copy vendor display_settings.xml"); + } + } } @Override diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 422b6e58e0ed..85ba95f7d6de 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -90,24 +90,11 @@ class KeyguardController { } /** - * @return true if either Keyguard or AOD are showing, not going away, and not being occluded - * on the given display, false otherwise. + * @return true if either 1) AOD is showing, or 2) Keyguard is showing, not going away, and not + * being occluded on the given display, false otherwise. */ boolean isKeyguardOrAodShowing(int displayId) { - return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway - && !isDisplayOccluded(displayId); - } - - /** - * @return {@code true} for default display when AOD is showing. Otherwise, same as - * {@link #isKeyguardOrAodShowing(int)} - * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic. - */ - boolean isKeyguardUnoccludedOrAodShowing(int displayId) { - if (displayId == DEFAULT_DISPLAY && mAodShowing) { - return true; - } - return isKeyguardOrAodShowing(displayId); + return mAodShowing || isKeyguardShowing(displayId); } /** @@ -115,7 +102,7 @@ class KeyguardController { * display, false otherwise */ boolean isKeyguardShowing(int displayId) { - return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId); + return mKeyguardShowing && !mKeyguardGoingAway && !isKeyguardOccluded(displayId); } /** @@ -328,7 +315,7 @@ class KeyguardController { return; } - mWindowManager.onKeyguardOccludedChanged(isDisplayOccluded(DEFAULT_DISPLAY)); + mWindowManager.onKeyguardOccludedChanged(isKeyguardOccluded(DEFAULT_DISPLAY)); if (isKeyguardLocked()) { mWindowManager.deferSurfaceLayout(); try { @@ -373,7 +360,7 @@ class KeyguardController { } } - private boolean isDisplayOccluded(int displayId) { + private boolean isKeyguardOccluded(int displayId) { return getDisplay(displayId).mOccluded; } @@ -391,13 +378,13 @@ class KeyguardController { if (mBeforeUnoccludeTransit != TRANSIT_UNSET && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE // TODO(b/113840485): Handle app transition for individual display. - && isDisplayOccluded(DEFAULT_DISPLAY)) { + && isKeyguardOccluded(DEFAULT_DISPLAY)) { // Reuse old transit in case we are occluding Keyguard again, meaning that we never // actually occclude/unocclude Keyguard, but just run a normal transition. return mBeforeUnoccludeTransit; // TODO(b/113840485): Handle app transition for individual display. - } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) { + } else if (!isKeyguardOccluded(DEFAULT_DISPLAY)) { // Save transit in case we dismiss/occlude Keyguard shortly after. mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition(); @@ -409,7 +396,7 @@ class KeyguardController { private void dismissDockedStackIfNeeded() { // TODO(b/113840485): Handle docked stack for individual display. - if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) { + if (mKeyguardShowing && isKeyguardOccluded(DEFAULT_DISPLAY)) { // The lock screen is currently showing, but is occluded by a window that can // show on top of the lock screen. In this can we want to dismiss the docked // stack since it will be complicated/risky to try to put the activity on top @@ -434,9 +421,9 @@ class KeyguardController { private void updateKeyguardSleepToken(int displayId) { final KeyguardDisplayState state = getDisplay(displayId); - if (isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken == null) { + if (isKeyguardOrAodShowing(displayId) && state.mSleepToken == null) { state.acquiredSleepToken(); - } else if (!isKeyguardUnoccludedOrAodShowing(displayId) && state.mSleepToken != null) { + } else if (!isKeyguardOrAodShowing(displayId) && state.mSleepToken != null) { state.releaseSleepToken(); } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index bf627ec5680c..0a3e7a4860d5 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -355,7 +355,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks, // launch-behind state is restored. That also prevents the next transition // type being disturbed if the visibility is updated after setting the next // transition (the target activity will be one of closing apps). - if (!controller.shouldCancelWithDeferredScreenshot() + if (!controller.shouldDeferCancelWithScreenshot() && !targetStack.isFocusedStackOnDisplay()) { targetStack.ensureActivitiesVisibleLocked(null /* starting */, 0 /* starting */, false /* preserveWindows */); @@ -415,16 +415,18 @@ class RecentsAnimation implements RecentsAnimationCallbacks, final DisplayContent dc = mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent; dc.mBoundsAnimationController.setAnimationType( - controller.shouldCancelWithDeferredScreenshot() ? FADE_IN : BOUNDS); + controller.shouldDeferCancelUntilNextTransition() ? FADE_IN : BOUNDS); - // Cancel running recents animation and screenshot previous task when the next - // transition starts in below cases: - // 1) The next launching task is not in recents animation task. + // We defer canceling the recents animation until the next app transition in the following + // cases: + // 1) The next launching task is not being animated by the recents animation // 2) The next task is home activity. (i.e. pressing home key to back home in recents). if ((!controller.isAnimatingTask(stack.getTaskStack().getTopChild()) || controller.isTargetApp(stack.getTopActivity().mAppWindowToken)) - && controller.shouldCancelWithDeferredScreenshot()) { - controller.cancelOnNextTransitionStart(); + && controller.shouldDeferCancelUntilNextTransition()) { + // Always prepare an app transition since we rely on the transition callbacks to cleanup + mWindowManager.prepareAppTransition(TRANSIT_NONE, false); + controller.setCancelOnNextTransitionStart(); } else { // Just cancel directly to unleash from launcher when the next launching task is the // current top task. diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 163be1ebd0ed..6ea4d580ea98 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -97,10 +97,9 @@ public class RecentsAnimationController implements DeathRecipient { private final Runnable mFailsafeRunnable = () -> cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "failSafeRunnable"); - final Object mLock = new Object(); - // The recents component app token that is shown behind the visibile tasks private AppWindowToken mTargetAppToken; + private DisplayContent mDisplayContent; private int mTargetActivityType; private Rect mMinimizedHomeBounds = new Rect(); @@ -124,25 +123,47 @@ public class RecentsAnimationController implements DeathRecipient { private boolean mLinkedToDeathOfRunner; - private boolean mCancelWithDeferredScreenshot; - + // Whether to try to defer canceling from a stack order change until the next transition + private boolean mRequestDeferCancelUntilNextTransition; + // Whether to actually defer canceling until the next transition private boolean mCancelOnNextTransitionStart; + // Whether to take a screenshot when handling a deferred cancel + private boolean mCancelDeferredWithScreenshot; /** * Animates the screenshot of task that used to be controlled by RecentsAnimation. - * @see {@link #cancelOnNextTransitionStart} + * @see {@link #setCancelOnNextTransitionStart} */ SurfaceAnimator mRecentScreenshotAnimator; + /** + * An app transition listener to cancel the recents animation only after the app transition + * starts or is canceled. + */ final AppTransitionListener mAppTransitionListener = new AppTransitionListener() { @Override public int onAppTransitionStartingLocked(int transit, long duration, long statusBarAnimationStartTime, long statusBarAnimationDuration) { - onTransitionStart(); - mService.mRoot.getDisplayContent(mDisplayId).mAppTransition - .unregisterListener(this); + continueDeferredCancel(); return 0; } + + @Override + public void onAppTransitionCancelledLocked(int transit) { + continueDeferredCancel(); + } + + private void continueDeferredCancel() { + mDisplayContent.mAppTransition.unregisterListener(this); + if (mCanceled) { + return; + } + + if (mCancelOnNextTransitionStart) { + mCancelOnNextTransitionStart = false; + cancelAnimationWithScreenshot(mCancelDeferredWithScreenshot); + } + } }; public interface RecentsAnimationCallbacks { @@ -202,8 +223,7 @@ public class RecentsAnimationController implements DeathRecipient { ? REORDER_MOVE_TO_TOP : REORDER_MOVE_TO_ORIGINAL_POSITION, true /* runSynchronously */, sendUserLeaveHint); - final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId); - dc.mBoundsAnimationController.setAnimationType(FADE_IN); + mDisplayContent.mBoundsAnimationController.setAnimationType(FADE_IN); } finally { Binder.restoreCallingIdentity(token); } @@ -240,8 +260,7 @@ public class RecentsAnimationController implements DeathRecipient { } mInputConsumerEnabled = enabled; - final InputMonitor inputMonitor = - mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor(); + final InputMonitor inputMonitor = mDisplayContent.getInputMonitor(); inputMonitor.updateInputWindowsLw(true /*force*/); mService.scheduleAnimationLocked(); } @@ -282,15 +301,23 @@ public class RecentsAnimationController implements DeathRecipient { } @Override + @Deprecated public void setCancelWithDeferredScreenshot(boolean screenshot) { - synchronized (mLock) { - setCancelWithDeferredScreenshotLocked(screenshot); + synchronized (mService.mGlobalLock) { + setDeferredCancel(true /* deferred */, screenshot); + } + } + + @Override + public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) { + synchronized (mService.mGlobalLock) { + setDeferredCancel(defer, screenshot); } } @Override public void cleanupScreenshot() { - synchronized (mLock) { + synchronized (mService.mGlobalLock) { if (mRecentScreenshotAnimator != null) { mRecentScreenshotAnimator.cancelAnimation(); mRecentScreenshotAnimator = null; @@ -312,10 +339,7 @@ public class RecentsAnimationController implements DeathRecipient { mCallbacks = callbacks; mDisplayId = displayId; mStatusBar = LocalServices.getService(StatusBarManagerInternal.class); - } - - public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) { - initialize(mService.mRoot.getDisplayContent(mDisplayId), targetActivityType, recentTaskIds); + mDisplayContent = service.mRoot.getDisplayContent(displayId); } /** @@ -323,15 +347,15 @@ public class RecentsAnimationController implements DeathRecipient { * because it may call cancelAnimation() which needs to properly clean up the controller * in the window manager. */ - @VisibleForTesting - void initialize(DisplayContent dc, int targetActivityType, SparseBooleanArray recentTaskIds) { + public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) { mTargetActivityType = targetActivityType; - dc.mAppTransition.registerListenerLocked(mAppTransitionListener); + mDisplayContent.mAppTransition.registerListenerLocked(mAppTransitionListener); // Make leashes for each of the visible/target tasks and add it to the recents animation to // be started - final ArrayList<Task> visibleTasks = dc.getVisibleTasks(); - final TaskStack targetStack = dc.getStack(WINDOWING_MODE_UNDEFINED, targetActivityType); + final ArrayList<Task> visibleTasks = mDisplayContent.getVisibleTasks(); + final TaskStack targetStack = mDisplayContent.getStack(WINDOWING_MODE_UNDEFINED, + targetActivityType); if (targetStack != null) { for (int i = targetStack.getChildCount() - 1; i >= 0; i--) { final Task t = targetStack.getChildAt(i); @@ -365,29 +389,31 @@ public class RecentsAnimationController implements DeathRecipient { } // Adjust the wallpaper visibility for the showing target activity - final AppWindowToken recentsComponentAppToken = dc.getStack(WINDOWING_MODE_UNDEFINED, - targetActivityType).getTopChild().getTopFullscreenAppToken(); + final AppWindowToken recentsComponentAppToken = + targetStack.getTopChild().getTopFullscreenAppToken(); if (recentsComponentAppToken != null) { if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "setHomeApp(" + recentsComponentAppToken.getName() + ")"); mTargetAppToken = recentsComponentAppToken; if (recentsComponentAppToken.windowsCanBeWallpaperTarget()) { - dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; - dc.setLayoutNeeded(); + mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; + mDisplayContent.setLayoutNeeded(); } } // Save the minimized home height - final TaskStack dockedStack = dc.getSplitScreenPrimaryStackIgnoringVisibility(); - dc.getDockedDividerController().getHomeStackBoundsInDockedMode( - dc.getConfiguration(), + final TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility(); + mDisplayContent.getDockedDividerController().getHomeStackBoundsInDockedMode( + mDisplayContent.getConfiguration(), dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(), mMinimizedHomeBounds); mService.mWindowPlacerLocked.performSurfacePlacement(); // Notify that the animation has started - mStatusBar.onRecentsAnimationStateChanged(true /* running */); + if (mStatusBar != null) { + mStatusBar.onRecentsAnimationStateChanged(true /* running */); + } } @VisibleForTesting @@ -441,8 +467,7 @@ public class RecentsAnimationController implements DeathRecipient { // Perform layout if it was scheduled before to make sure that we get correct content // insets for the target app window after a rotation - final DisplayContent displayContent = mService.mRoot.getDisplayContent(mDisplayId); - displayContent.performLayout(false /* initial */, false /* updateInputWindows */); + mDisplayContent.performLayout(false /* initial */, false /* updateInputWindows */); final Rect minimizedHomeBounds = mTargetAppToken != null && mTargetAppToken.inSplitScreenSecondaryWindowingMode() @@ -480,9 +505,8 @@ public class RecentsAnimationController implements DeathRecipient { cancelAnimation(reorderMode, true /* runSynchronously */, false /* screenshot */, reason); } - void cancelAnimationWithScreenShot() { - cancelAnimation(REORDER_KEEP_IN_PLACE, true /* sync */, true /* screenshot */, - "stackOrderChanged"); + void cancelAnimationWithScreenshot(boolean screenshot) { + cancelAnimation(REORDER_KEEP_IN_PLACE, true /* sync */, screenshot, "stackOrderChanged"); } private void cancelAnimation(@ReorderMode int reorderMode, boolean runSynchronously, @@ -496,21 +520,29 @@ public class RecentsAnimationController implements DeathRecipient { } mService.mH.removeCallbacks(mFailsafeRunnable); mCanceled = true; - try { - if (screenshot) { - // Screen shot previous task when next task starts transition. - final Task task = mPendingAnimations.get(0).mTask; - screenshotRecentTask(task, reorderMode, runSynchronously); + + if (screenshot) { + // Screen shot previous task when next task starts transition and notify the runner. + // We will actually finish the animation once the runner calls cleanUpScreenshot(). + final Task task = mPendingAnimations.get(0).mTask; + screenshotRecentTask(task, reorderMode, runSynchronously); + try { mRunner.onAnimationCanceled(true /* deferredWithScreenshot */); - return; + } catch (RemoteException e) { + Slog.e(TAG, "Failed to cancel recents animation", e); + } + } else { + // Otherwise, notify the runner and clean up the animation immediately + // Note: In the fallback case, this can trigger multiple onAnimationCancel() calls + // to the runner if we this actually triggers cancel twice on the caller + try { + mRunner.onAnimationCanceled(false /* deferredWithScreenshot */); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to cancel recents animation", e); } - mRunner.onAnimationCanceled(false /* deferredWithScreenshot */); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to cancel recents animation", e); + mCallbacks.onAnimationFinished(reorderMode, runSynchronously, + false /* sendUserLeaveHint */); } - // Clean up and return to the previous app - mCallbacks.onAnimationFinished(reorderMode, runSynchronously, - false /* sendUserLeaveHint */); } } @@ -523,27 +555,36 @@ public class RecentsAnimationController implements DeathRecipient { * screenshot, so that Launcher can still control the leash lifecycle & make the next app * transition animate smoothly without flickering. */ - void cancelOnNextTransitionStart() { + void setCancelOnNextTransitionStart() { mCancelOnNextTransitionStart = true; } - void setCancelWithDeferredScreenshotLocked(boolean screenshot) { - mCancelWithDeferredScreenshot = screenshot; + /** + * Requests that we attempt to defer the cancel until the next app transition if we are + * canceling from a stack order change. If {@param screenshot} is specified, then the system + * will replace the contents of the leash with a screenshot, which must be cleaned up when the + * runner calls cleanUpScreenshot(). + */ + void setDeferredCancel(boolean defer, boolean screenshot) { + mRequestDeferCancelUntilNextTransition = defer; + mCancelDeferredWithScreenshot = screenshot; } - boolean shouldCancelWithDeferredScreenshot() { - return mCancelWithDeferredScreenshot; + /** + * @return Whether we should defer the cancel from a stack order change until the next app + * transition. + */ + boolean shouldDeferCancelUntilNextTransition() { + return mRequestDeferCancelUntilNextTransition; } - void onTransitionStart() { - if (mCanceled) { - return; - } - - if (mCancelOnNextTransitionStart) { - mCancelOnNextTransitionStart = false; - cancelAnimationWithScreenShot(); - } + /** + * @return Whether we should both defer the cancel from a stack order change until the next + * app transition, and also that the deferred cancel should replace the contents of the leash + * with a screenshot. + */ + boolean shouldDeferCancelWithScreenshot() { + return mRequestDeferCancelUntilNextTransition && mCancelDeferredWithScreenshot; } void screenshotRecentTask(Task task, @ReorderMode int reorderMode, boolean runSynchronously) { @@ -576,6 +617,7 @@ public class RecentsAnimationController implements DeathRecipient { // Clear any pending failsafe runnables mService.mH.removeCallbacks(mFailsafeRunnable); + mDisplayContent.mAppTransition.unregisterListener(mAppTransitionListener); // Clear references to the runner unlinkToDeathOfRunner(); @@ -589,21 +631,22 @@ public class RecentsAnimationController implements DeathRecipient { } // Update the input windows after the animation is complete - final InputMonitor inputMonitor = - mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor(); + final InputMonitor inputMonitor = mDisplayContent.getInputMonitor(); inputMonitor.updateInputWindowsLw(true /*force*/); // We have deferred all notifications to the target app as a part of the recents animation, // so if we are actually transitioning there, notify again here if (mTargetAppToken != null) { if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) { - mService.mRoot.getDisplayContent(mDisplayId) - .mAppTransition.notifyAppTransitionFinishedLocked(mTargetAppToken.token); + mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked( + mTargetAppToken.token); } } // Notify that the animation has ended - mStatusBar.onRecentsAnimationStateChanged(false /* running */); + if (mStatusBar != null) { + mStatusBar.onRecentsAnimationStateChanged(false /* running */); + } } void scheduleFailsafe() { @@ -630,8 +673,7 @@ public class RecentsAnimationController implements DeathRecipient { synchronized (mService.getWindowManagerLock()) { // Clear associated input consumers on runner death - final InputMonitor inputMonitor = - mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor(); + final InputMonitor inputMonitor = mDisplayContent.getInputMonitor(); inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION); } } @@ -827,5 +869,11 @@ public class RecentsAnimationController implements DeathRecipient { pw.print(innerPrefix); pw.println("mSplitScreenMinimized=" + mSplitScreenMinimized); pw.print(innerPrefix); pw.println("mTargetAppToken=" + mTargetAppToken); pw.print(innerPrefix); pw.println("isTargetOverWallpaper=" + isTargetOverWallpaper()); + pw.print(innerPrefix); pw.println("mRequestDeferCancelUntilNextTransition=" + + mRequestDeferCancelUntilNextTransition); + pw.print(innerPrefix); pw.println("mCancelOnNextTransitionStart=" + + mCancelOnNextTransitionStart); + pw.print(innerPrefix); pw.println("mCancelDeferredWithScreenshot=" + + mCancelDeferredWithScreenshot); } } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index dc62877bca8d..b94a7dc781e8 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -937,6 +937,7 @@ class ScreenRotationAnimation { } } + t.setEarlyWakeup(); setSnapshotTransform(t, mSnapshotFinalMatrix, mExitTransformation.getAlpha()); } diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index 23515d8619dd..882f41152886 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -66,6 +66,7 @@ import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY; import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY; import static com.android.server.am.TaskRecordProto.RESIZE_MODE; import static com.android.server.am.TaskRecordProto.STACK_ID; +import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED; import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP; @@ -1419,7 +1420,7 @@ class TaskRecord extends ConfigurationContainer { --activityNdx; --numActivities; } else if (r.finishActivityLocked(Activity.RESULT_CANCELED, null, - reason, false /* oomAdj */, pauseImmediately)) { + reason, false /* oomAdj */, pauseImmediately) == FINISH_RESULT_REMOVED) { --activityNdx; --numActivities; } @@ -1474,7 +1475,7 @@ class TaskRecord extends ConfigurationContainer { ret.updateOptionsLocked(opts); } if (r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */, - "clear-task-stack", false /* oomAdj */)) { + "clear-task-stack", false /* oomAdj */) == FINISH_RESULT_REMOVED) { --activityNdx; --numActivities; } diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java index 1a571683de34..143543e8c74b 100644 --- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java +++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java @@ -28,7 +28,7 @@ import android.view.SurfaceSession; * Class used by {@link RecentsAnimationController} to create a surface control with taking * screenshot of task when canceling recents animation. * - * @see {@link RecentsAnimationController#cancelOnNextTransitionStart} + * @see {@link RecentsAnimationController#setCancelOnNextTransitionStart} */ class TaskScreenshotAnimatable implements SurfaceAnimator.Animatable { private static final String TAG = "TaskScreenshotAnim"; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index eb45e73d47a4..79367a050d46 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -321,7 +321,9 @@ public class TaskStack extends WindowContainer<Task> implements */ private void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds, boolean toFullscreen) { - mBoundsAnimatingRequested = true; + if (mAnimationType == BoundsAnimationController.BOUNDS) { + mBoundsAnimatingRequested = true; + } mBoundsAnimatingToFullscreen = toFullscreen; if (destBounds != null) { mBoundsAnimationTarget.set(destBounds); @@ -1586,8 +1588,10 @@ public class TaskStack extends WindowContainer<Task> implements return false; } - mBoundsAnimatingRequested = false; - mBoundsAnimating = true; + if (animationType == BoundsAnimationController.BOUNDS) { + mBoundsAnimatingRequested = false; + mBoundsAnimating = true; + } mAnimationType = animationType; // If we are changing UI mode, as in the PiP to fullscreen diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 636f4e6d09d0..05cfbd4e39d9 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -511,4 +511,9 @@ public abstract class WindowManagerInternal { */ public abstract void removeNonHighRefreshRatePackage(@NonNull String packageName); + /** + * Checks if this display is touchable. + */ + public abstract boolean isTouchableDisplay(int displayId); + } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 70e446c51c43..fbdc54a2435b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -7455,6 +7455,17 @@ public class WindowManagerService extends IWindowManager.Stub .removeNonHighRefreshRatePackage(packageName)); } } + + @Override + public boolean isTouchableDisplay(int displayId) { + synchronized (mGlobalLock) { + final DisplayContent displayContent = mRoot.getDisplayContent(displayId); + final Configuration configuration = + displayContent != null ? displayContent.getConfiguration() : null; + return configuration != null + && configuration.touchscreen == Configuration.TOUCHSCREEN_FINGER; + } + } } void registerAppFreezeListener(AppFreezeListener listener) { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 3ba3280be7bb..41840a4c531c 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -729,12 +729,7 @@ class WindowStateAnimator { if (!mService.mLimitedAlphaCompositing || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy)))) { - //Slog.i(TAG_WM, "Applying alpha transform"); - if (screenAnimation) { - mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha(); - } - } else { - //Slog.i(TAG_WM, "Not applying alpha transform"); + mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha(); } if ((DEBUG_ANIM || WindowManagerService.localLOGV) @@ -1299,7 +1294,7 @@ class WindowStateAnimator { mSurfaceController.mSurfaceControl); } - mPostDrawTransaction.apply(); + SurfaceControl.mergeToGlobalTransaction(mPostDrawTransaction); return true; } diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 1c8c46c74002..466ca9315f6f 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -41,7 +41,6 @@ #include <utils/Looper.h> #include <utils/threads.h> #include <utils/Trace.h> -#include <utils/SortedVector.h> #include <binder/IServiceManager.h> @@ -307,7 +306,7 @@ private: wp<PointerController> pointerController; // Input devices to be disabled - SortedVector<int32_t> disabledInputDevices; + std::set<int32_t> disabledInputDevices; // Associated Pointer controller display. int32_t pointerDisplayId; @@ -898,13 +897,13 @@ void NativeInputManager::setInputDeviceEnabled(uint32_t deviceId, bool enabled) { // acquire lock AutoMutex _l(mLock); - ssize_t index = mLocked.disabledInputDevices.indexOf(deviceId); - bool currentlyEnabled = index < 0; + auto it = mLocked.disabledInputDevices.find(deviceId); + bool currentlyEnabled = it == mLocked.disabledInputDevices.end(); if (!enabled && currentlyEnabled) { - mLocked.disabledInputDevices.add(deviceId); + mLocked.disabledInputDevices.insert(deviceId); } if (enabled && !currentlyEnabled) { - mLocked.disabledInputDevices.remove(deviceId); + mLocked.disabledInputDevices.erase(deviceId); } } // release lock diff --git a/services/core/xsd/Android.bp b/services/core/xsd/Android.bp index 98e4343e6e57..8b2cbbde2db8 100644 --- a/services/core/xsd/Android.bp +++ b/services/core/xsd/Android.bp @@ -4,3 +4,11 @@ xsd_config { api_dir: "schema", package_name: "com.android.server.pm.permission.configfile", } + + +xsd_config { + name: "platform-compat-config", + srcs: ["platform-compat-config.xsd"], + api_dir: "platform-compat-schema", + package_name: "com.android.server.compat.config", +} diff --git a/services/core/xsd/platform-compat-config.xsd b/services/core/xsd/platform-compat-config.xsd new file mode 100644 index 000000000000..ee39e507aff1 --- /dev/null +++ b/services/core/xsd/platform-compat-config.xsd @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- This defines the format of the XML file generated by + ~ com.android.compat.annotation.ChangeIdProcessor annotation processor (from + ~ tools/platform-compat), and is parsed in com/android/server/compat/CompatConfig.java. +--> +<xs:schema version="2.0" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <xs:complexType name="change"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:long" name="id" use="required"/> + <xs:attribute type="xs:string" name="name" use="required"/> + <xs:attribute type="xs:boolean" name="disabled"/> + <xs:attribute type="xs:int" name="enableAfterTargetSdk"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:element name="config"> + <xs:complexType> + <xs:sequence> + <xs:element name="compat-change" type="change" maxOccurs="unbounded" + minOccurs="0"/> + </xs:sequence> + </xs:complexType> + <xs:unique name="UniqueId"> + <xs:selector xpath="compat-change" /> + <xs:field xpath="@id" /> + </xs:unique> + </xs:element> +</xs:schema> + + + + diff --git a/services/core/xsd/platform-compat-schema/current.txt b/services/core/xsd/platform-compat-schema/current.txt new file mode 100644 index 000000000000..84567851da2c --- /dev/null +++ b/services/core/xsd/platform-compat-schema/current.txt @@ -0,0 +1,31 @@ +// Signature format: 2.0 +package com.android.server.compat.config { + + public class Change { + ctor public Change(); + method public boolean getDisabled(); + method public int getEnableAfterTargetSdk(); + method public long getId(); + method public String getName(); + method public String getValue(); + method public void setDisabled(boolean); + method public void setEnableAfterTargetSdk(int); + method public void setId(long); + method public void setName(String); + method public void setValue(String); + } + + public class Config { + ctor public Config(); + method public java.util.List<com.android.server.compat.config.Change> getCompatChange(); + } + + public class XmlParser { + ctor public XmlParser(); + method public static com.android.server.compat.config.Config read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + } + +} + diff --git a/services/core/xsd/platform-compat-schema/last_current.txt b/services/core/xsd/platform-compat-schema/last_current.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/services/core/xsd/platform-compat-schema/last_current.txt diff --git a/services/core/xsd/platform-compat-schema/last_removed.txt b/services/core/xsd/platform-compat-schema/last_removed.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/services/core/xsd/platform-compat-schema/last_removed.txt diff --git a/services/core/xsd/platform-compat-schema/removed.txt b/services/core/xsd/platform-compat-schema/removed.txt new file mode 100644 index 000000000000..d802177e249b --- /dev/null +++ b/services/core/xsd/platform-compat-schema/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a04875f1a283..9fe44dc7b2f0 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -87,6 +87,7 @@ import com.android.server.biometrics.iris.IrisService; import com.android.server.broadcastradio.BroadcastRadioService; import com.android.server.camera.CameraServiceProxy; import com.android.server.clipboard.ClipboardService; +import com.android.server.compat.PlatformCompat; import com.android.server.connectivity.IpConnectivityMetrics; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.coverage.CoverageService; @@ -1098,6 +1099,11 @@ public final class SystemServer { t.traceBegin("SignedConfigService"); SignedConfigService.registerUpdateReceiver(mSystemContext); t.traceEnd(); + + t.traceBegin("PlatformCompat"); + ServiceManager.addService("platform_compat", new PlatformCompat(context)); + t.traceEnd(); + } catch (RuntimeException e) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting core service", e); diff --git a/services/robotests/Android.bp b/services/robotests/Android.bp new file mode 100644 index 000000000000..3ce514a56b60 --- /dev/null +++ b/services/robotests/Android.bp @@ -0,0 +1,53 @@ +// Copyright (C) 2016 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. + +//################################################################## +// FrameworksServicesLib app just for Robolectric test target # +//################################################################## + +android_app { + name: "FrameworksServicesLib", + platform_apis: true, + + privileged: true, + + static_libs: [ + "services.core", + "services.net", + ], +} + +//################################################################## +// FrameworksServicesLib Robolectric test target. # +//################################################################## +android_robolectric_test { + name: "FrameworksServicesRoboTests", + + srcs: ["src/**/*.java"], + + java_resource_dirs: ["config"], + + // Include the testing libraries + libs: [ + "platform-test-annotations", + "testng", + ], + + instrumentation_for: "FrameworksServicesLib", +} + +filegroup { + name: "FrameworksServicesRoboShadows", + srcs: ["src/com/android/server/testing/shadows/**/*.java"], +} diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk deleted file mode 100644 index 0cf0d3402dea..000000000000 --- a/services/robotests/Android.mk +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (C) 2016 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. - -################################################################### -# FrameworksServicesLib app just for Robolectric test target # -################################################################### -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_PACKAGE_NAME := FrameworksServicesLib -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_MODULE_TAGS := optional - -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_STATIC_JAVA_LIBRARIES := \ - services.core \ - services.net - -include $(BUILD_PACKAGE) - -################################################################### -# FrameworksServicesLib Robolectric test target. # -################################################################### -include $(CLEAR_VARS) - -LOCAL_MODULE := FrameworksServicesRoboTests - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_RESOURCE_DIR := \ - $(LOCAL_PATH)/res - -LOCAL_JAVA_RESOURCE_DIRS := config - -# Include the testing libraries -LOCAL_JAVA_LIBRARIES := \ - platform-test-annotations \ - robolectric_android-all-stub \ - Robolectric_all-target \ - mockito-robolectric-prebuilt \ - truth-prebuilt \ - testng - -LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_STATIC_JAVA_LIBRARY) - -################################################################### -# FrameworksServicesLib runner target to run the previous target. # -################################################################### -include $(CLEAR_VARS) - -LOCAL_MODULE := RunFrameworksServicesRoboTests - -LOCAL_JAVA_LIBRARIES := \ - FrameworksServicesRoboTests \ - platform-test-annotations \ - robolectric_android-all-stub \ - Robolectric_all-target \ - mockito-robolectric-prebuilt \ - truth-prebuilt \ - testng - -LOCAL_TEST_PACKAGE := FrameworksServicesLib - -LOCAL_ROBOTEST_FILES := $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.) - -include external/robolectric-shadows/run_robotests.mk - -################################################################### -# include subdir Android.mk files -################################################################### -include $(CLEAR_VARS) -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/services/robotests/AndroidManifest.xml b/services/robotests/AndroidManifest.xml new file mode 100644 index 000000000000..828c8fade6fc --- /dev/null +++ b/services/robotests/AndroidManifest.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + coreApp="true" + package="com.android.server.robotests"> + + <application/> + +</manifest> diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp new file mode 100644 index 000000000000..9d384e90d253 --- /dev/null +++ b/services/robotests/backup/Android.bp @@ -0,0 +1,53 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//################################################################## +// BackupFrameworksServicesLib app just for Robolectric test target # +//################################################################## +android_app { + name: "BackupFrameworksServicesLib", + platform_apis: true, + + privileged: true, + + static_libs: [ + "bmgr", + "bu", + "services.backup", + "services.core", + "services.net", + ], +} + +//################################################################## +// BackupFrameworksServicesLib Robolectric test target. # +//################################################################## +android_robolectric_test { + name: "BackupFrameworksServicesRoboTests", + srcs: [ + "src/**/*.java", + ":FrameworksServicesRoboShadows", + ], + + java_resource_dirs: ["config"], + + // Include the testing libraries + libs: [ + "platform-test-annotations", + "testng", + ], + + instrumentation_for: "BackupFrameworksServicesLib", + +} diff --git a/services/robotests/backup/Android.mk b/services/robotests/backup/Android.mk deleted file mode 100644 index bd4ebbd393fa..000000000000 --- a/services/robotests/backup/Android.mk +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) - -################################################################### -# BackupFrameworksServicesLib app just for Robolectric test target # -################################################################### -include $(CLEAR_VARS) - -LOCAL_PACKAGE_NAME := BackupFrameworksServicesLib -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_MODULE_TAGS := optional - -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_STATIC_JAVA_LIBRARIES := \ - bmgr \ - bu \ - services.backup \ - services.core \ - services.net - -include $(BUILD_PACKAGE) - -################################################################### -# BackupFrameworksServicesLib Robolectric test target. # -################################################################### -include $(CLEAR_VARS) - -LOCAL_MODULE := BackupFrameworksServicesRoboTests - -LOCAL_SRC_FILES := $(call all-java-files-under, src) \ - $(call all-java-files-under, ../src/com/android/server/testing/shadows) - -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res - -LOCAL_JAVA_RESOURCE_DIRS := config - -# Include the testing libraries -LOCAL_JAVA_LIBRARIES := \ - platform-test-annotations \ - robolectric_android-all-stub \ - Robolectric_all-target \ - mockito-robolectric-prebuilt \ - truth-prebuilt \ - testng - -LOCAL_INSTRUMENTATION_FOR := BackupFrameworksServicesLib - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_STATIC_JAVA_LIBRARY) - -################################################################### -# BackupFrameworksServicesLib runner target to run the previous target. # -################################################################### -include $(CLEAR_VARS) - -LOCAL_MODULE := RunBackupFrameworksServicesRoboTests - -LOCAL_JAVA_LIBRARIES := \ - BackupFrameworksServicesRoboTests \ - platform-test-annotations \ - robolectric_android-all-stub \ - Robolectric_all-target \ - mockito-robolectric-prebuilt \ - truth-prebuilt \ - testng - -LOCAL_TEST_PACKAGE := BackupFrameworksServicesLib - -include external/robolectric-shadows/run_robotests.mk diff --git a/services/robotests/backup/AndroidManifest.xml b/services/robotests/backup/AndroidManifest.xml new file mode 100644 index 000000000000..09323782a228 --- /dev/null +++ b/services/robotests/backup/AndroidManifest.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + coreApp="true" + package="com.android.server.backup.robotests"> + + <application/> + +</manifest> diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java index 06c83a26cca6..6feac520e538 100644 --- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java @@ -53,6 +53,7 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.longThat; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; @@ -129,9 +130,12 @@ public class DeviceIdleControllerTest { ConnectivityService connectivityService; LocationManager locationManager; ConstraintController constraintController; + // Freeze time for testing. + long nowElapsed; InjectorForTest(Context ctx) { super(ctx); + nowElapsed = SystemClock.elapsedRealtime(); } @Override @@ -156,6 +160,11 @@ public class DeviceIdleControllerTest { } @Override + long getElapsedRealtime() { + return nowElapsed; + } + + @Override LocationManager getLocationManager() { return locationManager; } @@ -494,11 +503,44 @@ public class DeviceIdleControllerTest { mDeviceIdleController.becomeActiveLocked("testing", 0); verifyStateConditions(STATE_ACTIVE); + setAlarmSoon(false); + setChargingOn(false); + setScreenOn(false); + + mDeviceIdleController.becomeInactiveIfAppropriateLocked(); + verifyStateConditions(STATE_INACTIVE); + verify(mDeviceIdleController) + .scheduleAlarmLocked(eq(mConstants.INACTIVE_TIMEOUT), eq(false)); + } + + @Test + public void testStateActiveToStateInactive_UpcomingAlarm() { + final long timeUntilAlarm = mConstants.MIN_TIME_TO_ALARM / 2; + // Set an upcoming alarm that will prevent full idle. + doReturn(mInjector.getElapsedRealtime() + timeUntilAlarm) + .when(mAlarmManager).getNextWakeFromIdleTime(); + + InOrder inOrder = inOrder(mDeviceIdleController); + + enterDeepState(STATE_ACTIVE); + setQuickDozeEnabled(false); setChargingOn(false); setScreenOn(false); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_INACTIVE); + inOrder.verify(mDeviceIdleController) + .scheduleAlarmLocked(eq(timeUntilAlarm + mConstants.INACTIVE_TIMEOUT), eq(false)); + + enterDeepState(STATE_ACTIVE); + setQuickDozeEnabled(true); + setChargingOn(false); + setScreenOn(false); + + mDeviceIdleController.becomeInactiveIfAppropriateLocked(); + verifyStateConditions(STATE_QUICK_DOZE_DELAY); + inOrder.verify(mDeviceIdleController).scheduleAlarmLocked( + eq(timeUntilAlarm + mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false)); } @Test @@ -515,42 +557,68 @@ public class DeviceIdleControllerTest { @Test public void testTransitionFromAnyStateToStateQuickDozeDelay() { + setAlarmSoon(false); + InOrder inOrder = inOrder(mDeviceIdleController); + enterDeepState(STATE_ACTIVE); setQuickDozeEnabled(true); setChargingOn(false); setScreenOn(false); verifyStateConditions(STATE_QUICK_DOZE_DELAY); + inOrder.verify(mDeviceIdleController) + .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false)); enterDeepState(STATE_INACTIVE); setQuickDozeEnabled(true); verifyStateConditions(STATE_QUICK_DOZE_DELAY); + inOrder.verify(mDeviceIdleController) + .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false)); enterDeepState(STATE_IDLE_PENDING); setQuickDozeEnabled(true); verifyStateConditions(STATE_QUICK_DOZE_DELAY); + inOrder.verify(mDeviceIdleController) + .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false)); enterDeepState(STATE_SENSING); setQuickDozeEnabled(true); verifyStateConditions(STATE_QUICK_DOZE_DELAY); + inOrder.verify(mDeviceIdleController) + .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false)); enterDeepState(STATE_LOCATING); setQuickDozeEnabled(true); verifyStateConditions(STATE_QUICK_DOZE_DELAY); + inOrder.verify(mDeviceIdleController) + .scheduleAlarmLocked(eq(mConstants.QUICK_DOZE_DELAY_TIMEOUT), eq(false)); // IDLE should stay as IDLE. enterDeepState(STATE_IDLE); + // Clear out any alarm setting from the order before checking for this section. + inOrder.verify(mDeviceIdleController, atLeastOnce()) + .scheduleAlarmLocked(anyLong(), anyBoolean()); setQuickDozeEnabled(true); verifyStateConditions(STATE_IDLE); + inOrder.verify(mDeviceIdleController, never()).scheduleAlarmLocked(anyLong(), anyBoolean()); // IDLE_MAINTENANCE should stay as IDLE_MAINTENANCE. enterDeepState(STATE_IDLE_MAINTENANCE); + // Clear out any alarm setting from the order before checking for this section. + inOrder.verify(mDeviceIdleController, atLeastOnce()) + .scheduleAlarmLocked(anyLong(), anyBoolean()); setQuickDozeEnabled(true); verifyStateConditions(STATE_IDLE_MAINTENANCE); + inOrder.verify(mDeviceIdleController, never()).scheduleAlarmLocked(anyLong(), anyBoolean()); + // State is already QUICK_DOZE_DELAY. No work should be done. enterDeepState(STATE_QUICK_DOZE_DELAY); + // Clear out any alarm setting from the order before checking for this section. + inOrder.verify(mDeviceIdleController, atLeastOnce()) + .scheduleAlarmLocked(anyLong(), anyBoolean()); setQuickDozeEnabled(true); mDeviceIdleController.becomeInactiveIfAppropriateLocked(); verifyStateConditions(STATE_QUICK_DOZE_DELAY); + inOrder.verify(mDeviceIdleController, never()).scheduleAlarmLocked(anyLong(), anyBoolean()); } @Test diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 869913dec646..0614b3a40cb2 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -39,6 +39,7 @@ android_test { "platformprotosnano", "hamcrest-library", "servicestests-utils", + "xml-writer-device-lib", ], aidl: { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java index aad7230bbc89..cdcc338b3928 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityGestureDetectorTest.java @@ -16,6 +16,7 @@ package com.android.server.accessibility; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; @@ -174,6 +175,7 @@ public class AccessibilityGestureDetectorTest { } // Check that correct gesture was recognized. - verify(mResultListener).onGestureCompleted(gestureId); + verify(mResultListener).onGestureCompleted( + argThat(gestureInfo -> gestureInfo.getGestureId() == gestureId)); } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java index ba2959f7f965..2f9f9bbecbdf 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java @@ -23,21 +23,25 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.accessibilityservice.AccessibilityServiceInfo; +import android.accessibilityservice.GestureDescription; import android.accessibilityservice.IAccessibilityServiceClient; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; +import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; +import android.view.Display; import com.android.server.wm.WindowManagerInternal; @@ -50,6 +54,7 @@ import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; /** @@ -73,6 +78,9 @@ public class AccessibilityServiceConnectionTest { @Mock GlobalActionPerformer mMockGlobalActionPerformer; @Mock KeyEventDispatcher mMockKeyEventDispatcher; @Mock MagnificationController mMockMagnificationController; + @Mock IBinder mMockIBinder; + @Mock IAccessibilityServiceClient mMockServiceClient; + @Mock MotionEventInjector mMockMotionEventInjector; MessageCapturingHandler mHandler = new MessageCapturingHandler(null); @@ -82,15 +90,22 @@ public class AccessibilityServiceConnectionTest { when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher); when(mMockSystemSupport.getMagnificationController()) .thenReturn(mMockMagnificationController); + when(mMockSystemSupport.getMotionEventInjectorForDisplayLocked( + Display.DEFAULT_DISPLAY)).thenReturn(mMockMotionEventInjector); when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo); mMockResolveInfo.serviceInfo = mock(ServiceInfo.class); mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class); + when(mMockIBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient); + when(mMockWindowManagerInternal.isTouchableDisplay(Display.DEFAULT_DISPLAY)).thenReturn( + true); + mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext, COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(), mMockSecurityPolicy, mMockSystemSupport, mMockWindowManagerInternal, mMockGlobalActionPerformer, mMockA11yWindowManager); + when(mMockSecurityPolicy.canPerformGestures(mConnection)).thenReturn(true); } @After @@ -115,25 +130,23 @@ public class AccessibilityServiceConnectionTest { @Test public void bindConnectUnbind_linksAndUnlinksToServiceDeath() throws RemoteException { - IBinder mockBinder = mock(IBinder.class); setServiceBinding(COMPONENT_NAME); mConnection.bindLocked(); - mConnection.onServiceConnected(COMPONENT_NAME, mockBinder); - verify(mockBinder).linkToDeath(eq(mConnection), anyInt()); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); + verify(mMockIBinder).linkToDeath(eq(mConnection), anyInt()); mConnection.unbindLocked(); - verify(mockBinder).unlinkToDeath(eq(mConnection), anyInt()); + verify(mMockIBinder).unlinkToDeath(eq(mConnection), anyInt()); } @Test public void connectedServiceCrashedAndRestarted_crashReportedInServiceInfo() { - IBinder mockBinder = mock(IBinder.class); setServiceBinding(COMPONENT_NAME); mConnection.bindLocked(); - mConnection.onServiceConnected(COMPONENT_NAME, mockBinder); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); assertFalse(mConnection.getServiceInfo().crashed); mConnection.binderDied(); assertTrue(mConnection.getServiceInfo().crashed); - mConnection.onServiceConnected(COMPONENT_NAME, mockBinder); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); mHandler.sendAllMessages(); assertFalse(mConnection.getServiceInfo().crashed); } @@ -145,10 +158,9 @@ public class AccessibilityServiceConnectionTest { @Test public void binderDied_keysGetFlushed() { - IBinder mockBinder = mock(IBinder.class); setServiceBinding(COMPONENT_NAME); mConnection.bindLocked(); - mConnection.onServiceConnected(COMPONENT_NAME, mockBinder); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); mConnection.binderDied(); assertTrue(mConnection.getServiceInfo().crashed); verify(mMockKeyEventDispatcher).flush(mConnection); @@ -157,17 +169,63 @@ public class AccessibilityServiceConnectionTest { @Test public void connectedService_notInEnabledServiceList_doNotInitClient() throws RemoteException { - IBinder mockBinder = mock(IBinder.class); - IAccessibilityServiceClient mockClient = mock(IAccessibilityServiceClient.class); - when(mockBinder.queryLocalInterface(any())).thenReturn(mockClient); when(mMockUserState.getEnabledServicesLocked()) .thenReturn(Collections.emptySet()); setServiceBinding(COMPONENT_NAME); mConnection.bindLocked(); - mConnection.onServiceConnected(COMPONENT_NAME, mockBinder); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); mHandler.sendAllMessages(); verify(mMockSystemSupport, times(2)).onClientChangeLocked(false); - verify(mockClient, times(0)).init(any(), anyInt(), any()); + verify(mMockServiceClient, times(0)).init(any(), anyInt(), any()); + } + + @Test + public void sendGesture_touchableDisplay_injectEvents() + throws RemoteException { + setServiceBinding(COMPONENT_NAME); + mConnection.bindLocked(); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); + + ParceledListSlice parceledListSlice = mock(ParceledListSlice.class); + List<GestureDescription.GestureStep> gestureSteps = mock(List.class); + when(parceledListSlice.getList()).thenReturn(gestureSteps); + mConnection.dispatchGesture(0, parceledListSlice, Display.DEFAULT_DISPLAY); + + verify(mMockMotionEventInjector).injectEvents(gestureSteps, mMockServiceClient, 0); + } + + @Test + public void sendGesture_untouchableDisplay_performGestureResultFailed() + throws RemoteException { + when(mMockWindowManagerInternal.isTouchableDisplay(Display.DEFAULT_DISPLAY)).thenReturn( + false); + setServiceBinding(COMPONENT_NAME); + mConnection.bindLocked(); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); + + ParceledListSlice parceledListSlice = mock(ParceledListSlice.class); + List<GestureDescription.GestureStep> gestureSteps = mock(List.class); + when(parceledListSlice.getList()).thenReturn(gestureSteps); + mConnection.dispatchGesture(0, parceledListSlice, Display.DEFAULT_DISPLAY); + + verify(mMockMotionEventInjector, never()).injectEvents(gestureSteps, mMockServiceClient, 0); + verify(mMockServiceClient).onPerformGestureResult(0, false); } + + @Test + public void sendGesture_invalidDisplay_performGestureResultFailed() + throws RemoteException { + setServiceBinding(COMPONENT_NAME); + mConnection.bindLocked(); + mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); + + ParceledListSlice parceledListSlice = mock(ParceledListSlice.class); + List<GestureDescription.GestureStep> gestureSteps = mock(List.class); + when(parceledListSlice.getList()).thenReturn(gestureSteps); + mConnection.dispatchGesture(0, parceledListSlice, Display.INVALID_DISPLAY); + + verify(mMockServiceClient).onPerformGestureResult(0, false); + } + } diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java index e6c484a8dbbc..f3c5e99f5f90 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java @@ -22,9 +22,17 @@ import android.content.pm.ApplicationInfo; import androidx.test.runner.AndroidJUnit4; +import com.android.compat.annotation.Change; +import com.android.compat.annotation.XmlWriter; + import org.junit.Test; import org.junit.runner.RunWith; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.UUID; + @RunWith(AndroidJUnit4.class) public class CompatConfigTest { @@ -35,6 +43,27 @@ public class CompatConfigTest { return ai; } + private File createTempDir() { + String base = System.getProperty("java.io.tmpdir"); + File dir = new File(base, UUID.randomUUID().toString()); + assertThat(dir.mkdirs()).isTrue(); + return dir; + } + + private void writeChangesToFile(Change[] changes, File f) { + XmlWriter writer = new XmlWriter(); + for (Change change: changes) { + writer.addChange(change); + } + try { + f.createNewFile(); + writer.write(new FileOutputStream(f)); + } catch (IOException e) { + throw new RuntimeException( + "Encountered an error while writing compat config file", e); + } + } + @Test public void testUnknownChangeEnabled() { CompatConfig pc = new CompatConfig(); @@ -142,4 +171,73 @@ public class CompatConfigTest { CompatConfig pc = new CompatConfig(); assertThat(pc.lookupChangeId("MY_CHANGE")).isEqualTo(-1L); } + + @Test + public void testSystemAppDisabledChangeEnabled() { + CompatConfig pc = new CompatConfig(); + pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, true)); // disabled + ApplicationInfo sysApp = makeAppInfo("system.app", 1); + sysApp.flags |= ApplicationInfo.FLAG_SYSTEM; + assertThat(pc.isChangeEnabled(1234L, sysApp)).isTrue(); + } + + @Test + public void testSystemAppOverrideIgnored() { + CompatConfig pc = new CompatConfig(); + pc.addChange(new CompatChange(1234L, "MY_CHANGE", -1, false)); + pc.addOverride(1234L, "system.app", false); + ApplicationInfo sysApp = makeAppInfo("system.app", 1); + sysApp.flags |= ApplicationInfo.FLAG_SYSTEM; + assertThat(pc.isChangeEnabled(1234L, sysApp)).isTrue(); + } + + @Test + public void testSystemAppTargetSdkIgnored() { + CompatConfig pc = new CompatConfig(); + pc.addChange(new CompatChange(1234L, "MY_CHANGE", 2, false)); + ApplicationInfo sysApp = makeAppInfo("system.app", 1); + sysApp.flags |= ApplicationInfo.FLAG_SYSTEM; + assertThat(pc.isChangeEnabled(1234L, sysApp)).isTrue(); + } + + @Test + public void testReadConfig() { + Change[] changes = {new Change(1234L, "MY_CHANGE1", false, 2), new Change(1235L, + "MY_CHANGE2", true, null), new Change(1236L, "MY_CHANGE3", false, null)}; + + File dir = createTempDir(); + writeChangesToFile(changes, new File(dir.getPath() + "/platform_compat_config.xml")); + + CompatConfig pc = new CompatConfig(); + pc.initConfigFromLib(dir); + + assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse(); + assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue(); + assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse(); + assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue(); + } + + @Test + public void testReadConfigMultipleFiles() { + Change[] changes1 = {new Change(1234L, "MY_CHANGE1", false, 2)}; + Change[] changes2 = {new Change(1235L, "MY_CHANGE2", true, null), new Change(1236L, + "MY_CHANGE3", false, null)}; + + File dir = createTempDir(); + writeChangesToFile(changes1, + new File(dir.getPath() + "/libcore_platform_compat_config.xml")); + writeChangesToFile(changes2, + new File(dir.getPath() + "/frameworks_platform_compat_config.xml")); + + + CompatConfig pc = new CompatConfig(); + pc.initConfigFromLib(dir); + + assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 1))).isFalse(); + assertThat(pc.isChangeEnabled(1234L, makeAppInfo("com.some.package", 3))).isTrue(); + assertThat(pc.isChangeEnabled(1235L, makeAppInfo("com.some.package", 5))).isFalse(); + assertThat(pc.isChangeEnabled(1236L, makeAppInfo("com.some.package", 1))).isTrue(); + } } + + diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageBuilder.java new file mode 100644 index 000000000000..470d4fa92833 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/PackageBuilder.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.pm.PackageParser; + +import com.android.internal.util.ArrayUtils; + +class PackageBuilder { + final PackageParser.Package mPkg; + + PackageBuilder(String packageName) { + mPkg = new PackageParser.Package(packageName); + } + + PackageBuilder setApplicationInfoCodePath(String codePath) { + mPkg.applicationInfo.setCodePath(codePath); + return this; + } + + PackageBuilder setApplicationInfoResourcePath(String resourcePath) { + mPkg.applicationInfo.setResourcePath(resourcePath); + return this; + } + + PackageBuilder setCodePath(String codePath) { + mPkg.codePath = codePath; + return this; + } + + PackageBuilder setBaseCodePath(String baseCodePath) { + mPkg.baseCodePath = baseCodePath; + return this; + } + + PackageBuilder addUsesStaticLibrary(String name, long version) { + mPkg.usesStaticLibraries = ArrayUtils.add(mPkg.usesStaticLibraries, name); + mPkg.usesStaticLibrariesVersions = + ArrayUtils.appendLong(mPkg.usesStaticLibrariesVersions, version); + return this; + } + + PackageBuilder setApplicationInfoNativeLibraryRootDir(String dir) { + mPkg.applicationInfo.nativeLibraryRootDir = dir; + return this; + } + + PackageBuilder setStaticSharedLib(String staticSharedLibName, long staticSharedLibVersion) { + mPkg.staticSharedLibVersion = staticSharedLibVersion; + mPkg.staticSharedLibName = staticSharedLibName; + return this; + } + + PackageBuilder setManifestPackageName(String manifestPackageName) { + mPkg.manifestPackageName = manifestPackageName; + return this; + } + + PackageBuilder setVersionCodeMajor(int versionCodeMajor) { + mPkg.mVersionCodeMajor = versionCodeMajor; + return this; + } + + PackageBuilder setVersionCode(int versionCode) { + mPkg.mVersionCode = versionCode; + return this; + } + + PackageBuilder addSplitCodePath(String splitCodePath) { + mPkg.splitCodePaths = + ArrayUtils.appendElement(String.class, mPkg.splitCodePaths, splitCodePath); + return this; + } + + PackageBuilder setApplicationInfoVolumeUuid(String volumeUuid) { + mPkg.applicationInfo.volumeUuid = volumeUuid; + return this; + } + + PackageBuilder addLibraryName(String libraryName) { + mPkg.libraryNames = ArrayUtils.add(mPkg.libraryNames, libraryName); + return this; + } + + PackageBuilder setRealPackageName(String realPackageName) { + mPkg.mRealPackage = realPackageName; + return this; + } + + PackageBuilder setCpuAbiOVerride(String cpuAbiOverride) { + mPkg.cpuAbiOverride = cpuAbiOverride; + return this; + } + + PackageBuilder addPermissionRequest(String permissionName) { + mPkg.requestedPermissions.add(permissionName); + return this; + } + + PackageParser.Package build() { + return mPkg; + } + + public PackageBuilder addApplicationInfoFlag(int flag) { + mPkg.applicationInfo.flags |= flag; + return this; + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index 13a8eb1d7fad..e33d8ca66ed0 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; @@ -557,6 +558,9 @@ public class PackageParserTest { pkg.mRequiredForAllUsers = true; pkg.visibleToInstantApps = true; pkg.use32bitAbi = true; + pkg.mForceQueryable = true; + pkg.mQueriesPackages = new ArrayList<>(Arrays.asList("foo27")); + pkg.mQueriesIntents = new ArrayList<>(Arrays.asList(new Intent("foo28"))); } private static void assertAllFieldsExist(PackageParser.Package pkg) throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java new file mode 100644 index 000000000000..b42cfd8be4a6 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.pm.PackageUserState; +import android.util.SparseArray; + +import java.io.File; +import java.util.List; + +class PackageSettingBuilder { + private String mName; + private String mRealName; + private String mCodePath; + private String mResourcePath; + private String mLegacyNativeLibraryPathString; + private String mPrimaryCpuAbiString; + private String mSecondaryCpuAbiString; + private String mCpuAbiOverrideString; + private long mPVersionCode; + private int mPkgFlags; + private int mPrivateFlags; + private String mParentPackageName; + private List<String> mChildPackageNames; + private int mSharedUserId; + private String[] mUsesStaticLibraries; + private long[] mUsesStaticLibrariesVersions; + private String mVolumeUuid; + private SparseArray<PackageUserState> mUserStates = new SparseArray<>(); + + public PackageSettingBuilder setName(String name) { + this.mName = name; + return this; + } + + public PackageSettingBuilder setRealName(String realName) { + this.mRealName = realName; + return this; + } + + public PackageSettingBuilder setCodePath(String codePath) { + this.mCodePath = codePath; + return this; + } + + public PackageSettingBuilder setResourcePath(String resourcePath) { + this.mResourcePath = resourcePath; + return this; + } + + public PackageSettingBuilder setLegacyNativeLibraryPathString( + String legacyNativeLibraryPathString) { + this.mLegacyNativeLibraryPathString = legacyNativeLibraryPathString; + return this; + } + + public PackageSettingBuilder setPrimaryCpuAbiString(String primaryCpuAbiString) { + this.mPrimaryCpuAbiString = primaryCpuAbiString; + return this; + } + + public PackageSettingBuilder setSecondaryCpuAbiString(String secondaryCpuAbiString) { + this.mSecondaryCpuAbiString = secondaryCpuAbiString; + return this; + } + + public PackageSettingBuilder setCpuAbiOverrideString(String cpuAbiOverrideString) { + this.mCpuAbiOverrideString = cpuAbiOverrideString; + return this; + } + + public PackageSettingBuilder setPVersionCode(long pVersionCode) { + this.mPVersionCode = pVersionCode; + return this; + } + + public PackageSettingBuilder setPkgFlags(int pkgFlags) { + this.mPkgFlags = pkgFlags; + return this; + } + + public PackageSettingBuilder setPrivateFlags(int privateFlags) { + this.mPrivateFlags = privateFlags; + return this; + } + + public PackageSettingBuilder setParentPackageName(String parentPackageName) { + this.mParentPackageName = parentPackageName; + return this; + } + + public PackageSettingBuilder setChildPackageNames(List<String> childPackageNames) { + this.mChildPackageNames = childPackageNames; + return this; + } + + public PackageSettingBuilder setSharedUserId(int sharedUserId) { + this.mSharedUserId = sharedUserId; + return this; + } + + public PackageSettingBuilder setUsesStaticLibraries(String[] usesStaticLibraries) { + this.mUsesStaticLibraries = usesStaticLibraries; + return this; + } + + public PackageSettingBuilder setUsesStaticLibrariesVersions( + long[] usesStaticLibrariesVersions) { + this.mUsesStaticLibrariesVersions = usesStaticLibrariesVersions; + return this; + } + + public PackageSettingBuilder setVolumeUuid(String volumeUuid) { + this.mVolumeUuid = volumeUuid; + return this; + } + + public PackageSettingBuilder setInstantAppUserState(int userId, boolean isInstant) { + if (mUserStates.indexOfKey(userId) < 0) { + mUserStates.put(userId, new PackageUserState()); + } + mUserStates.get(userId).instantApp = isInstant; + return this; + } + + public PackageSetting build() { + final PackageSetting packageSetting = new PackageSetting(mName, mRealName, + new File(mCodePath), new File(mResourcePath), + mLegacyNativeLibraryPathString, mPrimaryCpuAbiString, mSecondaryCpuAbiString, + mCpuAbiOverrideString, mPVersionCode, mPkgFlags, mPrivateFlags, mParentPackageName, + mChildPackageNames, mSharedUserId, mUsesStaticLibraries, + mUsesStaticLibrariesVersions); + packageSetting.volumeUuid = this.mVolumeUuid; + for (int i = 0; i < mUserStates.size(); i++) { + packageSetting.setUserState(mUserStates.keyAt(i), mUserStates.valueAt(i)); + } + return packageSetting; + + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java new file mode 100644 index 000000000000..34a3f860496a --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.pm.PackageParser; +import android.os.UserHandle; + +class ScanRequestBuilder { + private final PackageParser.Package mPkg; + private PackageParser.Package mOldPkg; + private SharedUserSetting mSharedUserSetting; + private PackageSetting mPkgSetting; + private PackageSetting mDisabledPkgSetting; + private PackageSetting mOriginalPkgSetting; + private String mRealPkgName; + private int mParseFlags; + private int mScanFlags; + private UserHandle mUser; + private boolean mIsPlatformPackage; + + ScanRequestBuilder(PackageParser.Package pkg) { + this.mPkg = pkg; + } + + public ScanRequestBuilder setOldPkg(PackageParser.Package oldPkg) { + this.mOldPkg = oldPkg; + return this; + } + + public ScanRequestBuilder setSharedUserSetting(SharedUserSetting sharedUserSetting) { + this.mSharedUserSetting = sharedUserSetting; + return this; + } + + public ScanRequestBuilder setPkgSetting(PackageSetting pkgSetting) { + this.mPkgSetting = pkgSetting; + return this; + } + + public ScanRequestBuilder setDisabledPkgSetting(PackageSetting disabledPkgSetting) { + this.mDisabledPkgSetting = disabledPkgSetting; + return this; + } + + public ScanRequestBuilder setOriginalPkgSetting(PackageSetting originalPkgSetting) { + this.mOriginalPkgSetting = originalPkgSetting; + return this; + } + + public ScanRequestBuilder setRealPkgName(String realPkgName) { + this.mRealPkgName = realPkgName; + return this; + } + + public ScanRequestBuilder setParseFlags(int parseFlags) { + this.mParseFlags = parseFlags; + return this; + } + + public ScanRequestBuilder addParseFlag(int parseFlag) { + this.mParseFlags |= parseFlag; + return this; + } + + public ScanRequestBuilder setScanFlags(int scanFlags) { + this.mScanFlags = scanFlags; + return this; + } + + public ScanRequestBuilder addScanFlag(int scanFlag) { + this.mScanFlags |= scanFlag; + return this; + } + + public ScanRequestBuilder setUser(UserHandle user) { + this.mUser = user; + return this; + } + + public ScanRequestBuilder setIsPlatformPackage(boolean isPlatformPackage) { + this.mIsPlatformPackage = isPlatformPackage; + return this; + } + + PackageManagerService.ScanRequest build() { + return new PackageManagerService.ScanRequest( + mPkg, mSharedUserSetting, mOldPkg, mPkgSetting, mDisabledPkgSetting, + mOriginalPkgSetting, mRealPkgName, mParseFlags, mScanFlags, mIsPlatformPackage, + mUser); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java new file mode 100644 index 000000000000..cc70ef89c75f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import static android.content.pm.SharedLibraryInfo.TYPE_DYNAMIC; +import static android.content.pm.SharedLibraryInfo.TYPE_STATIC; +import static android.content.pm.SharedLibraryInfo.VERSION_UNDEFINED; + +import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP; +import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP; +import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE; +import static com.android.server.pm.PackageManagerService.SCAN_NEW_INSTALL; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertNotSame; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.Manifest; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageParser; +import android.content.pm.SharedLibraryInfo; +import android.os.Environment; +import android.os.UserHandle; +import android.os.UserManagerInternal; +import android.platform.test.annotations.Presubmit; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.io.File; + +@RunWith(MockitoJUnitRunner.class) +@Presubmit +public class ScanTests { + + private static final String DUMMY_PACKAGE_NAME = "some.app.to.test"; + + @Mock + PackageAbiHelper mMockPackageAbiHelper; + @Mock + UserManagerInternal mMockUserManager; + + @Before + public void setupDefaultUser() { + when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); + } + + @Test + public void newInstallSimpleAllNominal() throws Exception { + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .addScanFlag(PackageManagerService.SCAN_NEW_INSTALL) + .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) + .build(); + + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); + assertThat(scanResult.existingSettingCopied, is(false)); + verify(mMockPackageAbiHelper, never()).derivePackageAbi(any(PackageParser.Package.class), + anyString() /*abioverride*/, anyBoolean() /*extractNativeLibs*/); + verify(mMockPackageAbiHelper).setNativeLibraryPaths( + scanResult.pkgSetting.pkg, PackageManagerService.sAppLib32InstallDir); + } + + @Test + public void newInstallForAllUsers() throws Exception { + final int[] userIds = {0, 10, 11}; + when(mMockUserManager.getUserIds()).thenReturn(userIds); + + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .setRealPkgName(null) + .addScanFlag(PackageManagerService.SCAN_NEW_INSTALL) + .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) + .build(); + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + for (int uid : userIds) { + assertThat(scanResult.pkgSetting.readUserState(uid).installed, is(true)); + } + } + + @Test + public void installRealPackageName() throws Exception { + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .setRealPkgName("com.package.real") + .build(); + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertThat(scanResult.pkgSetting.realName, is("com.package.real")); + + final PackageManagerService.ScanRequest scanRequestNoRealPkg = + createBasicScanRequestBuilder( + createBasicPackage(DUMMY_PACKAGE_NAME) + .setRealPackageName("com.package.real").build()) + .build(); + + final PackageManagerService.ScanResult scanResultNoReal = executeScan(scanRequestNoRealPkg); + assertThat(scanResultNoReal.pkgSetting.realName, nullValue()); + } + + @Test + public void updateSimpleNominal() throws Exception { + when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); + + final PackageSetting pkgSetting = createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) + .setPrimaryCpuAbiString("primaryCpuAbi") + .setSecondaryCpuAbiString("secondaryCpuAbi") + .build(); + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) + .setPkgSetting(pkgSetting) + .build(); + + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertThat(scanResult.existingSettingCopied, is(true)); + + // ensure we don't overwrite the existing pkgSetting, in case something post-scan fails + assertNotSame(pkgSetting, scanResult.pkgSetting); + + assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); + + assertThat(scanResult.pkgSetting.primaryCpuAbiString, is("primaryCpuAbi")); + assertThat(scanResult.pkgSetting.secondaryCpuAbiString, is("secondaryCpuAbi")); + assertThat(scanResult.pkgSetting.cpuAbiOverrideString, nullValue()); + + verify(mMockPackageAbiHelper, never()).derivePackageAbi(any(PackageParser.Package.class), + anyString() /*abioverride*/, anyBoolean() /*extractNativeLibs*/); + verify(mMockPackageAbiHelper).setNativeLibraryPaths( + scanResult.pkgSetting.pkg, PackageManagerService.sAppLib32InstallDir); + } + + @Test + public void updateInstantSimpleNominal() throws Exception { + when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); + + final PackageSetting existingPkgSetting = + createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) + .setInstantAppUserState(0, true) + .build(); + + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .setPkgSetting(existingPkgSetting) + .build(); + + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, true /*isInstant*/); + } + + @Test + public void installStaticSharedLibrary() throws Exception { + final PackageParser.Package pkg = createBasicPackage("static.lib.pkg.123") + .setStaticSharedLib("static.lib", 123L) + .setManifestPackageName("static.lib.pkg") + .setVersionCodeMajor(1) + .setVersionCode(234) + .setBaseCodePath("/some/path.apk") + .addSplitCodePath("/some/other/path.apk") + .build(); + + final PackageManagerService.ScanRequest scanRequest = new ScanRequestBuilder( + pkg).setUser(UserHandle.of(0)).build(); + + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertThat(scanResult.staticSharedLibraryInfo.getPackageName(), is("static.lib.pkg.123")); + assertThat(scanResult.staticSharedLibraryInfo.getName(), is("static.lib")); + assertThat(scanResult.staticSharedLibraryInfo.getLongVersion(), is(123L)); + assertThat(scanResult.staticSharedLibraryInfo.getType(), is(TYPE_STATIC)); + assertThat(scanResult.staticSharedLibraryInfo.getDeclaringPackage().getPackageName(), + is("static.lib.pkg")); + assertThat(scanResult.staticSharedLibraryInfo.getDeclaringPackage().getLongVersionCode(), + is(pkg.getLongVersionCode())); + assertThat(scanResult.staticSharedLibraryInfo.getAllCodePaths(), + hasItems("/some/path.apk", "/some/other/path.apk")); + assertThat(scanResult.staticSharedLibraryInfo.getDependencies(), nullValue()); + assertThat(scanResult.staticSharedLibraryInfo.getDependentPackages(), empty()); + } + + @Test + public void installDynamicLibraries() throws Exception { + final PackageParser.Package pkg = createBasicPackage("dynamic.lib.pkg") + .setManifestPackageName("dynamic.lib.pkg") + .addLibraryName("liba") + .addLibraryName("libb") + .setVersionCodeMajor(1) + .setVersionCode(234) + .setBaseCodePath("/some/path.apk") + .addSplitCodePath("/some/other/path.apk") + .build(); + + final PackageManagerService.ScanRequest scanRequest = + new ScanRequestBuilder(pkg).setUser(UserHandle.of(0)).build(); + + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + final SharedLibraryInfo dynamicLib0 = scanResult.dynamicSharedLibraryInfos.get(0); + assertThat(dynamicLib0.getPackageName(), is("dynamic.lib.pkg")); + assertThat(dynamicLib0.getName(), is("liba")); + assertThat(dynamicLib0.getLongVersion(), is((long) VERSION_UNDEFINED)); + assertThat(dynamicLib0.getType(), is(TYPE_DYNAMIC)); + assertThat(dynamicLib0.getDeclaringPackage().getPackageName(), is("dynamic.lib.pkg")); + assertThat(dynamicLib0.getDeclaringPackage().getLongVersionCode(), + is(pkg.getLongVersionCode())); + assertThat(dynamicLib0.getAllCodePaths(), + hasItems("/some/path.apk", "/some/other/path.apk")); + assertThat(dynamicLib0.getDependencies(), nullValue()); + assertThat(dynamicLib0.getDependentPackages(), empty()); + + final SharedLibraryInfo dynamicLib1 = scanResult.dynamicSharedLibraryInfos.get(1); + assertThat(dynamicLib1.getPackageName(), is("dynamic.lib.pkg")); + assertThat(dynamicLib1.getName(), is("libb")); + assertThat(dynamicLib1.getLongVersion(), is((long) VERSION_UNDEFINED)); + assertThat(dynamicLib1.getType(), is(TYPE_DYNAMIC)); + assertThat(dynamicLib1.getDeclaringPackage().getPackageName(), is("dynamic.lib.pkg")); + assertThat(dynamicLib1.getDeclaringPackage().getLongVersionCode(), + is(pkg.getLongVersionCode())); + assertThat(dynamicLib1.getAllCodePaths(), + hasItems("/some/path.apk", "/some/other/path.apk")); + assertThat(dynamicLib1.getDependencies(), nullValue()); + assertThat(dynamicLib1.getDependentPackages(), empty()); + } + + @Test + public void volumeUuidChangesOnUpdate() throws Exception { + final PackageSetting pkgSetting = + createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) + .setVolumeUuid("someUuid") + .build(); + + final PackageParser.Package basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) + .setApplicationInfoVolumeUuid("someNewUuid") + .build(); + + + final PackageManagerService.ScanResult scanResult = executeScan( + new ScanRequestBuilder(basicPackage).setPkgSetting(pkgSetting).build()); + + assertThat(scanResult.pkgSetting.volumeUuid, is("someNewUuid")); + } + + @Test + public void scanFirstBoot_derivesAbis() throws Exception { + final PackageSetting pkgSetting = + createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME).build(); + + final PackageParser.Package basicPackage = + createBasicPackage(DUMMY_PACKAGE_NAME) + .setCpuAbiOVerride("testOverride") + .build(); + + + executeScan(new ScanRequestBuilder(basicPackage) + .setPkgSetting(pkgSetting) + .addScanFlag(SCAN_FIRST_BOOT_OR_UPGRADE) + .build()); + + verify(mMockPackageAbiHelper).derivePackageAbi(basicPackage, "testOverride", true); + } + + @Test + public void scanWithOriginalPkgSetting_packageNameChanges() throws Exception { + final PackageSetting originalPkgSetting = + createBasicPackageSettingBuilder("original.package").build(); + + final PackageParser.Package basicPackage = + createBasicPackage(DUMMY_PACKAGE_NAME) + .build(); + + + final PackageManagerService.ScanResult result = + executeScan(new ScanRequestBuilder(basicPackage) + .setOriginalPkgSetting(originalPkgSetting) + .build()); + + assertThat(result.request.pkg.packageName, is("original.package")); + } + + @Test + public void updateInstant_changeToFull() throws Exception { + when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); + + final PackageSetting existingPkgSetting = + createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) + .setInstantAppUserState(0, true) + .build(); + + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .setPkgSetting(existingPkgSetting) + .addScanFlag(SCAN_AS_FULL_APP) + .build(); + + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); + } + + @Test + public void updateFull_changeToInstant() throws Exception { + when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); + + final PackageSetting existingPkgSetting = + createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) + .setInstantAppUserState(0, false) + .build(); + + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .setPkgSetting(existingPkgSetting) + .addScanFlag(SCAN_AS_INSTANT_APP) + .build(); + + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, true /*isInstant*/); + } + + @Test + public void updateSystemApp_applicationInfoFlagSet() throws Exception { + final PackageSetting existingPkgSetting = + createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME) + .setPkgFlags(ApplicationInfo.FLAG_SYSTEM) + .build(); + + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + .setPkgSetting(existingPkgSetting) + .setDisabledPkgSetting(existingPkgSetting) + .addScanFlag(SCAN_NEW_INSTALL) + .build(); + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertThat(scanResult.request.pkg.applicationInfo.flags, + hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)); + } + + @Test + public void factoryTestFlagSet() throws Exception { + final PackageParser.Package basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) + .addPermissionRequest(Manifest.permission.FACTORY_TEST) + .build(); + + final PackageManagerService.ScanResult scanResult = PackageManagerService.scanPackageOnlyLI( + createBasicScanRequestBuilder(basicPackage).build(), + new PackageManagerService.Injector(mMockUserManager, mMockPackageAbiHelper), + true /*isUnderFactoryTest*/, + System.currentTimeMillis()); + + assertThat(scanResult.request.pkg.applicationInfo.flags, + hasFlag(ApplicationInfo.FLAG_FACTORY_TEST)); + } + + @Test + public void scanSystemApp_isOrphanedTrue() throws Exception { + final PackageParser.Package pkg = createBasicPackage(DUMMY_PACKAGE_NAME) + .addApplicationInfoFlag(ApplicationInfo.FLAG_SYSTEM) + .build(); + + final PackageManagerService.ScanRequest scanRequest = + createBasicScanRequestBuilder(pkg) + .build(); + + final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); + + assertThat(scanResult.pkgSetting.isOrphaned, is(true)); + } + + private static Matcher<Integer> hasFlag(final int flag) { + return new BaseMatcher<Integer>() { + @Override public void describeTo(Description description) { + description.appendText("flags "); + } + + @Override public boolean matches(Object item) { + return ((int) item & flag) != 0; + } + + @Override + public void describeMismatch(Object item, Description mismatchDescription) { + mismatchDescription + .appendValue(item) + .appendText(" does not contain flag ") + .appendValue(flag); + } + }; + } + + private PackageManagerService.ScanResult executeScan( + PackageManagerService.ScanRequest scanRequest) throws PackageManagerException { + return PackageManagerService.scanPackageOnlyLI( + scanRequest, + new PackageManagerService.Injector(mMockUserManager, mMockPackageAbiHelper), + false /*isUnderFactoryTest*/, + System.currentTimeMillis()); + } + + private static String createResourcePath(String packageName) { + return "/data/app/" + packageName + "-randompath/base.apk"; + } + + private static String createCodePath(String packageName) { + return "/data/app/" + packageName + "-randompath"; + } + + private static PackageSettingBuilder createBasicPackageSettingBuilder(String packageName) { + return new PackageSettingBuilder() + .setName(packageName) + .setCodePath(createCodePath(packageName)) + .setResourcePath(createResourcePath(packageName)); + } + + private static ScanRequestBuilder createBasicScanRequestBuilder(PackageParser.Package pkg) { + return new ScanRequestBuilder(pkg) + .setUser(UserHandle.of(0)); + } + + + private static PackageBuilder createBasicPackage(String packageName) { + return new PackageBuilder(packageName) + .setCodePath("/data/tmp/randompath") + .setApplicationInfoCodePath(createCodePath(packageName)) + .setApplicationInfoResourcePath(createResourcePath(packageName)) + .setApplicationInfoVolumeUuid("volumeUuid") + .setBaseCodePath("/data/tmp/randompath/base.apk") + .addUsesStaticLibrary("some.static.library", 234L) + .addUsesStaticLibrary("some.other.static.library", 456L) + .setApplicationInfoNativeLibraryRootDir("/data/tmp/randompath/base.apk:/lib") + .setVersionCodeMajor(1) + .setVersionCode(2345); + } + + private static void assertBasicPackageScanResult( + PackageManagerService.ScanResult scanResult, String packageName, boolean isInstant) { + assertThat(scanResult.success, is(true)); + + final PackageSetting pkgSetting = scanResult.pkgSetting; + assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting); + + final ApplicationInfo applicationInfo = pkgSetting.pkg.applicationInfo; + verifyBasicApplicationInfo(scanResult, applicationInfo); + + } + + private static void assertBasicPackageSetting(PackageManagerService.ScanResult scanResult, + String packageName, boolean isInstant, PackageSetting pkgSetting) { + assertThat(pkgSetting.pkg.packageName, is(packageName)); + assertThat(pkgSetting.getInstantApp(0), is(isInstant)); + assertThat(pkgSetting.usesStaticLibraries, + arrayContaining("some.static.library", "some.other.static.library")); + assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L})); + assertThat(pkgSetting.pkg, is(scanResult.request.pkg)); + assertThat(pkgSetting.pkg.mExtras, is(pkgSetting)); + assertThat(pkgSetting.legacyNativeLibraryPathString, + is("/data/tmp/randompath/base.apk:/lib")); + assertThat(pkgSetting.codePath, is(new File(createCodePath(packageName)))); + assertThat(pkgSetting.resourcePath, is(new File(createResourcePath(packageName)))); + assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345))); + } + + private static void verifyBasicApplicationInfo(PackageManagerService.ScanResult scanResult, + ApplicationInfo applicationInfo) { + assertThat(applicationInfo.processName, is(scanResult.request.pkg.packageName)); + + final int uid = applicationInfo.uid; + assertThat(UserHandle.getUserId(uid), is(UserHandle.USER_SYSTEM)); + + final String calculatedCredentialId = Environment.getDataUserCePackageDirectory( + applicationInfo.volumeUuid, UserHandle.USER_SYSTEM, + scanResult.request.pkg.packageName).getAbsolutePath(); + assertThat(applicationInfo.credentialProtectedDataDir, is(calculatedCredentialId)); + assertThat(applicationInfo.dataDir, is(applicationInfo.credentialProtectedDataDir)); + } +} diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java index f5002ace6690..3b336eb7aec9 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java @@ -7,10 +7,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -159,4 +161,25 @@ public class PinnedSliceStateTest extends UiServiceTestCase { verify(mSliceService).removePinnedSlice(eq(TEST_URI)); assertFalse(mPinnedSliceManager.hasPinOrListener()); } + + @Test + public void testPinFailed() throws Exception { + // Throw exception when trying to pin + doAnswer(invocation -> { + throw new Exception("Pin failed"); + }).when(mIContentProvider).call( + anyString(), anyString(), anyString(), eq(null), any()); + + TestableLooper.get(this).processAllMessages(); + + // When pinned for the first time, a pinned message should be sent. + mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken); + TestableLooper.get(this).processAllMessages(); + + verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN), + eq(null), argThat(b -> { + assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI)); + return true; + })); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index ef11a437fcb1..7b252cbfc0b0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -31,6 +31,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; +import static com.android.server.wm.ActivityRecord.FINISH_RESULT_CANCELLED; +import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED; +import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REQUESTED; import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING; import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; @@ -681,6 +684,73 @@ public class ActivityRecordTests extends ActivityTestsBase { assertEquals(persistentSavedState, mActivity.getPersistentSavedState()); } + /** + * Verify that activity finish request is not performed if activity is finishing or is in + * incorrect state. + */ + @Test + public void testFinishActivityLocked_cancelled() { + // Mark activity as finishing + mActivity.finishing = true; + assertEquals("Duplicate finish request must be ignored", FINISH_RESULT_CANCELLED, + mActivity.finishActivityLocked(0 /* resultCode */, null /* resultData */, "test", + false /* oomAdj */)); + assertTrue(mActivity.finishing); + assertTrue(mActivity.isInStackLocked()); + + // Remove activity from task + mActivity.finishing = false; + mActivity.setTask(null); + assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_CANCELLED, + mActivity.finishActivityLocked(0 /* resultCode */, null /* resultData */, "test", + false /* oomAdj */)); + assertFalse(mActivity.finishing); + } + + /** + * Verify that activity finish request is requested, but not executed immediately if activity is + * not ready yet. + */ + @Test + public void testFinishActivityLocked_requested() { + mActivity.finishing = false; + assertEquals("Currently resumed activity be paused removal", FINISH_RESULT_REQUESTED, + mActivity.finishActivityLocked(0 /* resultCode */, null /* resultData */, "test", + false /* oomAdj */)); + assertTrue(mActivity.finishing); + assertTrue(mActivity.isInStackLocked()); + + // First request to finish activity must schedule a "destroy" request to the client. + // Activity must be removed from history after the client reports back or after timeout. + mActivity.finishing = false; + mActivity.setState(STOPPED, "test"); + assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_REQUESTED, + mActivity.finishActivityLocked(0 /* resultCode */, null /* resultData */, "test", + false /* oomAdj */)); + assertTrue(mActivity.finishing); + assertTrue(mActivity.isInStackLocked()); + } + + /** + * Verify that activity finish request removes activity immediately if it's ready. + */ + @Test + public void testFinishActivityLocked_removed() { + // Prepare the activity record to be ready for immediate removal. It should be invisible and + // have no process. Otherwise, request to finish it will send a message to client first. + mActivity.setState(STOPPED, "test"); + mActivity.visible = false; + mActivity.nowVisible = false; + // Set process to 'null' to allow immediate removal, but don't call mActivity.setProcess() - + // this will cause NPE when updating task's process. + mActivity.app = null; + assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_REMOVED, + mActivity.finishActivityLocked(0 /* resultCode */, null /* resultData */, "test", + false /* oomAdj */)); + assertTrue(mActivity.finishing); + assertFalse(mActivity.isInStackLocked()); + } + /** Setup {@link #mActivity} as a size-compat-mode-able activity without fixed orientation. */ private void prepareFixedAspectRatioUnresizableActivity() { setupDisplayContentForCompatDisplayInsets(); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java index 26cd63c62cc1..cd292b2494ff 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -25,6 +25,7 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions; @@ -35,10 +36,12 @@ import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_O import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import android.os.Binder; @@ -79,6 +82,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { // Hold the lock to protect the stubbing from being accessed by other threads. spyOn(mWm.mRoot); doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean()); + doReturn(mDisplayContent).when(mWm.mRoot).getDisplayContent(anyInt()); } when(mMockRunner.asBinder()).thenReturn(new Binder()); mController = new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks, @@ -135,7 +139,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { hiddenAppWindow.setHidden(true); mDisplayContent.getConfiguration().windowConfiguration.setRotation( mDisplayContent.getRotation()); - mController.initialize(mDisplayContent, ACTIVITY_TYPE_HOME, new SparseBooleanArray()); + mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray()); // Ensure that we are animating the target activity as well assertTrue(mController.isAnimatingTask(homeAppWindow.getTask())); @@ -144,7 +148,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { } @Test - public void testCancelAnimationWithScreenShot() throws Exception { + public void testDeferCancelAnimation() throws Exception { mWm.setRecentsAnimationController(mController); final AppWindowToken appWindow = createAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); @@ -156,8 +160,31 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */); assertTrue(mController.isAnimatingTask(appWindow.getTask())); - mController.setCancelWithDeferredScreenshotLocked(true); - mController.cancelAnimationWithScreenShot(); + mController.setDeferredCancel(true /* deferred */, false /* screenshot */); + mController.cancelAnimationWithScreenshot(false /* screenshot */); + verify(mMockRunner).onAnimationCanceled(false /* deferredWithScreenshot */); + assertNull(mController.mRecentScreenshotAnimator); + + // Simulate the app transition finishing + mController.mAppTransitionListener.onAppTransitionStartingLocked(0, 0, 0, 0); + verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true, false); + } + + @Test + public void testDeferCancelAnimationWithScreenShot() throws Exception { + mWm.setRecentsAnimationController(mController); + final AppWindowToken appWindow = createAppWindowToken(mDisplayContent, + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1"); + appWindow.addWindow(win1); + assertEquals(appWindow.getTask().getTopVisibleAppToken(), appWindow); + assertEquals(appWindow.findMainWindow(), win1); + + mController.addAnimation(appWindow.getTask(), false /* isRecentTaskInvisible */); + assertTrue(mController.isAnimatingTask(appWindow.getTask())); + + mController.setDeferredCancel(true /* deferred */, true /* screenshot */); + mController.cancelAnimationWithScreenshot(true /* screenshot */); verify(mMockRunner).onAnimationCanceled(true /* deferredWithScreenshot */); assertNotNull(mController.mRecentScreenshotAnimator); assertTrue(mController.mRecentScreenshotAnimator.isAnimating()); @@ -185,7 +212,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { // Assume appWindow transition should animate when no // IRecentsAnimationController#setCancelWithDeferredScreenshot called. - assertFalse(mController.shouldCancelWithDeferredScreenshot()); + assertFalse(mController.shouldDeferCancelWithScreenshot()); assertTrue(appWindow.shouldAnimate(TRANSIT_ACTIVITY_CLOSE)); } diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java index 9630b7d46e3c..0e119e3cc375 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java @@ -274,12 +274,13 @@ public class RecentsAnimationTest extends ActivityTestsBase { // Assume recents animation already started, set a state that cancel recents animation // with screenshot. - doReturn(true).when(mRecentsAnimationController).shouldCancelWithDeferredScreenshot(); + doReturn(true).when(mRecentsAnimationController).shouldDeferCancelUntilNextTransition(); + doReturn(true).when(mRecentsAnimationController).shouldDeferCancelWithScreenshot(); // Start another fullscreen activity. fullscreenStack2.moveToFront("Activity start"); - // Ensure that the recents animation was canceled by cancelOnNextTransitionStart(). - verify(mRecentsAnimationController, times(1)).cancelOnNextTransitionStart(); + // Ensure that the recents animation was canceled by setCancelOnNextTransitionStart(). + verify(mRecentsAnimationController, times(1)).setCancelOnNextTransitionStart(); } @Test @@ -315,7 +316,7 @@ public class RecentsAnimationTest extends ActivityTestsBase { // Ensure that the recents animation was NOT canceled verify(mService.mWindowManager, times(0)).cancelRecentsAnimationSynchronously( eq(REORDER_KEEP_IN_PLACE), any()); - verify(mRecentsAnimationController, times(0)).cancelOnNextTransitionStart(); + verify(mRecentsAnimationController, times(0)).setCancelOnNextTransitionStart(); } @Test diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java index 94352b21db87..99337565e128 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java @@ -104,8 +104,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // This is an indirect indication of the microphone being open in some other application. private boolean mServiceDisabled = false; - // Whether we have ANY recognition (keyphrase or generic) running. - private boolean mRecognitionRunning = false; + // Whether ANY recognition (keyphrase or generic) has been requested. + private boolean mRecognitionRequested = false; private PowerSaveModeListener mPowerSaveModeListener; @@ -252,11 +252,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } } - // Initialize power save, call active state monitoring logic. - if (!mRecognitionRunning) { - initializeTelephonyAndPowerStateListeners(); - } - // If the existing SoundModel is different (for the same UUID for Generic and same // keyphrase ID for voice), ensure that it is unloaded and stopped before proceeding. // This works for both keyphrase and generic models. This logic also ensures that a @@ -326,8 +321,16 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { modelData.setRecognitionConfig(recognitionConfig); modelData.setSoundModel(soundModel); - return startRecognitionLocked(modelData, + int status = startRecognitionLocked(modelData, false /* Don't notify for synchronous calls */); + + // Initialize power save, call active state monitoring logic. + if (status == STATUS_OK && !mRecognitionRequested) { + initializeTelephonyAndPowerStateListeners(); + mRecognitionRequested = true; + } + + return status; } } @@ -450,7 +453,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { modelData.clearCallback(); modelData.setRecognitionConfig(null); - if (!computeRecognitionRunningLocked()) { + if (!computeRecognitionRequestedLocked()) { internalClearGlobalStateLocked(); } @@ -1196,20 +1199,20 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } // Computes whether we have any recognition running at all (voice or generic). Sets - // the mRecognitionRunning variable with the result. - private boolean computeRecognitionRunningLocked() { + // the mRecognitionRequested variable with the result. + private boolean computeRecognitionRequestedLocked() { if (mModuleProperties == null || mModule == null) { - mRecognitionRunning = false; - return mRecognitionRunning; + mRecognitionRequested = false; + return mRecognitionRequested; } for (ModelData modelData : mModelDataMap.values()) { - if (modelData.isModelStarted()) { - mRecognitionRunning = true; - return mRecognitionRunning; + if (modelData.isRequested()) { + mRecognitionRequested = true; + return mRecognitionRequested; } } - mRecognitionRunning = false; - return mRecognitionRunning; + mRecognitionRequested = false; + return mRecognitionRequested; } // This class encapsulates the callbacks, state, handles and any other information that diff --git a/startop/apps/test/Android.bp b/startop/apps/test/Android.bp index 7a1678ac9a5a..a4906d7b4cd3 100644 --- a/startop/apps/test/Android.bp +++ b/startop/apps/test/Android.bp @@ -23,4 +23,5 @@ android_app { "src/FrameLayoutInflationActivity.java", "src/TextViewInflationActivity.java", ], + platform_apis: true, } diff --git a/startop/scripts/iorap/compiler.py b/startop/scripts/iorap/compiler.py index 1e15736b13a1..9527e28c94fe 100755 --- a/startop/scripts/iorap/compiler.py +++ b/startop/scripts/iorap/compiler.py @@ -27,16 +27,23 @@ import optparse import os import re import sys -from typing import Iterable, Optional +import tempfile +from pathlib import Path +from typing import Iterable, Optional, List from generated.TraceFile_pb2 import * from lib.inode2filename import Inode2Filename parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) -sys.path.append(parent_dir_name + "/trace_analyzer") -from lib.trace2db import Trace2Db, MmFilemapAddToPageCache, RawFtraceEntry +sys.path.append(parent_dir_name) +from trace_analyzer.lib.trace2db import Trace2Db, MmFilemapAddToPageCache, \ + RawFtraceEntry +import lib.cmd_utils as cmd_utils _PAGE_SIZE = 4096 # adb shell getconf PAGESIZE ## size of a memory page in bytes. +ANDROID_BUILD_TOP = Path(parent_dir_name).parents[3] +TRACECONV_BIN = ANDROID_BUILD_TOP.joinpath( + 'external/perfetto/tools/traceconv') class PageRun: """ @@ -190,12 +197,62 @@ def query_add_to_page_cache(trace2db: Trace2Db, trace_duration: Optional[int]): RawFtraceEntry.timestamp <= end_time).order_by( MmFilemapAddToPageCache.id).all() +def transform_perfetto_trace_to_systrace(path_to_perfetto_trace: str, + path_to_tmp_systrace: str) -> None: + """ Transforms the systrace file from perfetto trace. """ + cmd_utils.run_command_nofail([str(TRACECONV_BIN), + 'systrace', + path_to_perfetto_trace, + path_to_tmp_systrace]) + + +def run(sql_db_path:str, + trace_file:str, + trace_duration:Optional[int], + output_file:str, + inode_table:str, + filter:List[str]) -> int: + trace2db = Trace2Db(sql_db_path) + # Speed optimization: Skip any entries that aren't mm_filemap_add_to_pagecache. + trace2db.set_raw_ftrace_entry_filter(\ + lambda entry: entry['function'] == 'mm_filemap_add_to_page_cache') + # TODO: parse multiple trace files here. + parse_count = trace2db.parse_file_into_db(trace_file) + + mm_filemap_add_to_page_cache_rows = query_add_to_page_cache(trace2db, + trace_duration) + print("DONE. Parsed %d entries into sql db." %(len(mm_filemap_add_to_page_cache_rows))) + + page_runs = page_cache_entries_to_runs(mm_filemap_add_to_page_cache_rows) + print("DONE. Converted %d entries" %(len(page_runs))) + + # TODO: flags to select optimizations. + optimized_page_runs = optimize_page_runs(page_runs) + print("DONE. Optimized down to %d entries" %(len(optimized_page_runs))) + + print("Build protobuf...") + trace_file = build_protobuf(optimized_page_runs, inode_table, filter) + + print("Write protobuf to file...") + output_file = open(output_file, 'wb') + output_file.write(trace_file.SerializeToString()) + output_file.close() + + print("DONE") + + # TODO: Silent running mode [no output except on error] for build runs. + + return 0 + def main(argv): parser = optparse.OptionParser(usage="Usage: %prog [options]", description="Compile systrace file into TraceFile.pb") parser.add_option('-i', dest='inode_data_file', metavar='FILE', help='Read cached inode data from a file saved earlier with pagecache.py -d') parser.add_option('-t', dest='trace_file', metavar='FILE', help='Path to systrace file (trace.html) that will be parsed') + parser.add_option('--perfetto-trace', dest='perfetto_trace_file', + metavar='FILE', + help='Path to perfetto trace that will be parsed') parser.add_option('--db', dest='sql_db', metavar='FILE', help='Path to intermediate sqlite3 database [default: in-memory].') @@ -217,54 +274,42 @@ def main(argv): # TODO: OptionParser should have some flags to make these mandatory. if not options.inode_data_file: parser.error("-i is required") - if not options.trace_file: - parser.error("-t is required") + if not options.trace_file and not options.perfetto_trace_file: + parser.error("one of -t or --perfetto-trace is required") + if options.trace_file and options.perfetto_trace_file: + parser.error("please enter either -t or --perfetto-trace, not both") if not options.output_file: parser.error("-o is required") if options.launch_lock: print("INFO: Launch lock flag (-l) enabled; filtering all events not inside launch_lock.") - inode_table = Inode2Filename.new_from_filename(options.inode_data_file) - trace_file = open(options.trace_file) - sql_db_path = ":memory:" if options.sql_db: sql_db_path = options.sql_db - trace2db = Trace2Db(sql_db_path) - # Speed optimization: Skip any entries that aren't mm_filemap_add_to_pagecache. - trace2db.set_raw_ftrace_entry_filter(\ - lambda entry: entry['function'] == 'mm_filemap_add_to_page_cache') - # TODO: parse multiple trace files here. - parse_count = trace2db.parse_file_into_db(options.trace_file) - - mm_filemap_add_to_page_cache_rows = query_add_to_page_cache(trace2db, - options.trace_duration) - print("DONE. Parsed %d entries into sql db." %(len(mm_filemap_add_to_page_cache_rows))) - - page_runs = page_cache_entries_to_runs(mm_filemap_add_to_page_cache_rows) - print("DONE. Converted %d entries" %(len(page_runs))) - - # TODO: flags to select optimizations. - optimized_page_runs = optimize_page_runs(page_runs) - print("DONE. Optimized down to %d entries" %(len(optimized_page_runs))) - - print("Build protobuf...") - trace_file = build_protobuf(optimized_page_runs, inode_table, options.filter) - - print("Write protobuf to file...") - output_file = open(options.output_file, 'wb') - output_file.write(trace_file.SerializeToString()) - output_file.close() - - print("DONE") - - # TODO: Silent running mode [no output except on error] for build runs. - - return 0 + # if the input is systrace + if options.trace_file: + return run(sql_db_path, + options.trace_file, + options.trace_duration, + options.output_file, + inode_table, + options.filter) + + # if the input is perfetto trace + # TODO python 3.7 switch to using nullcontext + with tempfile.NamedTemporaryFile() as trace_file: + transform_perfetto_trace_to_systrace(options.perfetto_trace_file, + trace_file.name) + return run(sql_db_path, + trace_file.name, + options.trace_duration, + options.output_file, + inode_table, + options.filter) if __name__ == '__main__': print(sys.argv) diff --git a/startop/scripts/iorap/compiler_test.py b/startop/scripts/iorap/compiler_test.py index fcb7269ed8d2..b5d28b03a8d5 100644 --- a/startop/scripts/iorap/compiler_test.py +++ b/startop/scripts/iorap/compiler_test.py @@ -36,6 +36,8 @@ DIR = os.path.abspath(os.path.dirname(__file__)) TEXTCACHE = os.path.join(DIR, 'test_fixtures/compiler/common_textcache') SYSTRACE = os.path.join(DIR, 'test_fixtures/compiler/common_systrace') ARGV = [os.path.join(DIR, 'compiler.py'), '-i', TEXTCACHE, '-t', SYSTRACE] +PERFETTO_TRACE = os.path.join(DIR, + 'test_fixtures/compiler/common_perfetto_trace.pb') def assert_compile_result(output, expected, *extra_argv): argv = ARGV + ['-o', output] + [args for args in extra_argv] @@ -45,6 +47,18 @@ def assert_compile_result(output, expected, *extra_argv): with open(output, 'rb') as f1, open(expected, 'rb') as f2: assert f1.read() == f2.read() +### Unit tests - testing compiler code directly +def test_transform_perfetto_trace_to_systrace(tmpdir): + expected = os.path.join(DIR, + 'test_fixtures/compiler/test_result_systrace') + output = tmpdir.mkdir('compiler').join('tmp_systrace') + + compiler.transform_perfetto_trace_to_systrace(PERFETTO_TRACE, str(output)) + + with open(output, 'rb') as f1, open(expected, 'rb') as f2: + assert f1.read() == f2.read() + +### Functional tests - calls 'compiler.py --args...' def test_compiler_main(tmpdir): output = tmpdir.mkdir('compiler').join('output') diff --git a/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb b/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb Binary files differnew file mode 100644 index 000000000000..a47ad3d5d9ec --- /dev/null +++ b/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace b/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace new file mode 100644 index 000000000000..f731e73ba9b2 --- /dev/null +++ b/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace @@ -0,0 +1,748 @@ +TRACE: +# tracer: nop +# +# entries-in-buffer/entries-written: 30624/30624 #P:4 +# +# _-----=> irqs-off +# / _----=> need-resched +# | / _---=> hardirq/softirq +# || / _--=> preempt-depth +# ||| / delay +# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION +# | | | | |||| | | + <unknown>-27388 (-----) [004] .... 1920260.530929: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1461937 ofs=9535488 + <unknown>-27388 (-----) [005] .... 1920260.532161: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1344589 ofs=9474048 + <unknown>-27388 (-----) [005] .... 1920260.532183: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1153671 ofs=9478144 + <unknown>-27388 (-----) [005] .... 1920260.532184: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1219563 ofs=9482240 + <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1083162 ofs=9486336 + <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1147318 ofs=9490432 + <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1333594 ofs=9494528 + <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1375715 ofs=9498624 + <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1184831 ofs=9502720 + <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1241653 ofs=9506816 + <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1134975 ofs=9510912 + <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1145772 ofs=9515008 + <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1090457 ofs=9519104 + <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1137942 ofs=9523200 + <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1130123 ofs=9527296 + <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1208783 ofs=9531392 + <unknown>-27388 (-----) [005] .... 1920260.532192: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1294989 ofs=9539584 + <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1163979 ofs=9543680 + <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1350628 ofs=9547776 + <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1386717 ofs=9551872 + <unknown>-27388 (-----) [005] .... 1920260.532207: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1316148 ofs=9555968 + <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1316419 ofs=9560064 + <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1149076 ofs=9564160 + <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1372772 ofs=9568256 + <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1116389 ofs=9572352 + <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1325458 ofs=9576448 + <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1195423 ofs=9580544 + <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1250964 ofs=9584640 + <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1196027 ofs=9588736 + <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1354059 ofs=9592832 + <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1264649 ofs=9596928 + <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1245285 ofs=9601024 + <unknown>-27388 (-----) [005] .... 1920260.535119: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1411552 ofs=44244992 + <unknown>-27388 (-----) [005] .... 1920260.535129: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1483081 ofs=433524736 + <unknown>-27388 (-----) [004] .... 1920260.536144: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1276173 ofs=438185984 + <unknown>-27388 (-----) [004] .... 1920260.536462: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1174575 ofs=44249088 + <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1126294 ofs=44253184 + <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1248232 ofs=44257280 + <unknown>-27388 (-----) [004] .... 1920260.537065: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1332993 ofs=44240896 + <unknown>-27388 (-----) [006] .... 1920260.537646: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1153343 ofs=44400640 + <unknown>-27388 (-----) [005] .... 1920260.538777: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1358397 ofs=44474368 + <unknown>-12683 (-----) [006] .... 1920260.560094: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1426577 ofs=0 + <unknown>-12683 (-----) [006] .... 1920260.560105: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117587 ofs=1171456 + <unknown>-12683 (-----) [006] .... 1920260.561199: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099987 ofs=4096 + <unknown>-12683 (-----) [006] .... 1920260.561411: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099910 ofs=16384 + <unknown>-12683 (-----) [006] .... 1920260.561598: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099905 ofs=20480 + <unknown>-12683 (-----) [006] .... 1920260.561758: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099883 ofs=32768 + <unknown>-12683 (-----) [006] .... 1920260.562088: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099809 ofs=36864 + <unknown>-12683 (-----) [006] .... 1920260.562325: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099803 ofs=98304 + <unknown>-12683 (-----) [006] .... 1920260.562516: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099795 ofs=102400 + <unknown>-12683 (-----) [006] .... 1920260.563094: mm_filemap_add_to_page_cache: dev 0:64768 ino 1523 page=0000000000000000 pfn=1107649 ofs=12288 + <unknown>-12683 (-----) [006] .... 1920260.563105: mm_filemap_add_to_page_cache: dev 0:64768 ino 1523 page=0000000000000000 pfn=1269029 ofs=16384 + <unknown>-12683 (-----) [006] .... 1920260.563785: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1451096 ofs=8192 + <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1301480 ofs=12288 + <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1314353 ofs=16384 + <unknown>-12683 (-----) [006] .... 1920260.563791: mm_filemap_add_to_page_cache: dev 0:64768 ino 1242 page=0000000000000000 pfn=1216744 ofs=24576 + <unknown>-12683 (-----) [006] .... 1920260.564309: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099787 ofs=49152 + <unknown>-12683 (-----) [006] .... 1920260.564514: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1099778 ofs=53248 + <unknown>-12683 (-----) [005] .... 1920260.564756: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1148849 ofs=114688 + <unknown>-12683 (-----) [005] .... 1920260.564973: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1164731 ofs=118784 + <unknown>-12683 (-----) [005] .... 1920260.565000: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1170255 ofs=0 + <unknown>-12683 (-----) [005] .... 1920260.565003: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1181043 ofs=4096 + <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1296004 ofs=8192 + <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 26 page=0000000000000000 pfn=1102004 ofs=12288 + <unknown>-12683 (-----) [005] .... 1920260.565626: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1351232 ofs=470597632 + <unknown>-12683 (-----) [005] .... 1920260.565982: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1391336 ofs=40210432 + <unknown>-12683 (-----) [005] .... 1920260.565985: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267536 ofs=12668928 + <unknown>-27388 (-----) [007] .... 1920260.566082: mm_filemap_add_to_page_cache: dev 0:64768 ino 1416 page=0000000000000000 pfn=1256752 ofs=43921408 + <unknown>-12683 (-----) [005] .... 1920260.566516: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1110966 ofs=176226304 + <unknown>-12683 (-----) [005] .... 1920260.566519: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1060586 ofs=12967936 + <unknown>-12683 (-----) [004] .... 1920260.567773: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117234 ofs=421888 + <unknown>-12683 (-----) [005] .... 1920260.568604: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1210571 ofs=430080 + <unknown>-12683 (-----) [005] .... 1920260.568887: mm_filemap_add_to_page_cache: dev 0:64771 ino 105 page=0000000000000000 pfn=1055640 ofs=0 + <unknown>-12683 (-----) [005] .... 1920260.568908: mm_filemap_add_to_page_cache: dev 0:64771 ino 73 page=0000000000000000 pfn=1142694 ofs=0 + <unknown>-12683 (-----) [005] .... 1920260.568910: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1060788 ofs=299008 + <unknown>-12683 (-----) [005] .... 1920260.569418: mm_filemap_add_to_page_cache: dev 0:64771 ino 73 page=0000000000000000 pfn=1085046 ofs=4096 + <unknown>-12683 (-----) [005] .... 1920260.569640: mm_filemap_add_to_page_cache: dev 0:64771 ino 73 page=0000000000000000 pfn=1057135 ofs=8192 + <unknown>-12683 (-----) [005] .... 1920260.569833: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1058976 ofs=19406848 + <unknown>-12683 (-----) [005] .... 1920260.569835: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1477947 ofs=10526720 + <unknown>-12683 (-----) [005] .... 1920260.572285: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1237492 ofs=299008 + <unknown>-12683 (-----) [005] .... 1920260.572297: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1264914 ofs=339968 + <unknown>-12683 (-----) [005] .... 1920260.572314: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1434748 ofs=348160 + <unknown>-12683 (-----) [005] .... 1920260.572316: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1372959 ofs=352256 + <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1258955 ofs=356352 + <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1113420 ofs=360448 + <unknown>-12683 (-----) [005] .... 1920260.572318: mm_filemap_add_to_page_cache: dev 0:64768 ino 1565 page=0000000000000000 pfn=1137083 ofs=364544 + <unknown>-12683 (-----) [004] .... 1920260.575490: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1379679 ofs=65536 + <unknown>-12683 (-----) [006] .... 1920260.576194: mm_filemap_add_to_page_cache: dev 0:64771 ino 286 page=0000000000000000 pfn=1323898 ofs=69632 + <unknown>-12683 (-----) [006] .... 1920260.576248: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323895 ofs=262623232 + <unknown>-12683 (-----) [006] .... 1920260.576251: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323861 ofs=13156352 + <unknown>-12683 (-----) [005] .... 1920260.576810: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1477585 ofs=262590464 + <unknown>-12683 (-----) [004] .... 1920260.577197: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1267617 ofs=25206784 + <unknown>-12683 (-----) [004] .... 1920260.577200: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267618 ofs=12636160 + <unknown>-12683 (-----) [005] .... 1920260.577725: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1056225 ofs=228618240 + <unknown>-12683 (-----) [005] .... 1920260.577727: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1164942 ofs=13082624 + <unknown>-12683 (-----) [007] .... 1920260.578411: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1372616 ofs=0 + <unknown>-12683 (-----) [007] .... 1920260.578422: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1307468 ofs=4096 + <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1120117 ofs=8192 + <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1217989 ofs=12288 + <unknown>-12683 (-----) [007] .... 1920260.578650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1475011 ofs=5419008 + <unknown>-12683 (-----) [007] .... 1920260.578653: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1066084 ofs=236453888 + <unknown>-12683 (-----) [007] .... 1920260.578654: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1100271 ofs=13099008 + <unknown>-12683 (-----) [004] .... 1920260.579004: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1485156 ofs=5423104 + <unknown>-12683 (-----) [004] .... 1920260.579005: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1124212 ofs=5427200 + <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1195377 ofs=5431296 + <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1265888 ofs=5435392 + <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1170194 ofs=5439488 + <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1403742 ofs=5443584 + <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1123826 ofs=5447680 + <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1255034 ofs=5451776 + <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1190447 ofs=5455872 + <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1286864 ofs=5459968 + <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1428535 ofs=5464064 + <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1184092 ofs=5468160 + <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1411906 ofs=5472256 + <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1342349 ofs=5476352 + <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1188185 ofs=5480448 + <unknown>-12683 (-----) [004] .... 1920260.579014: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1158702 ofs=5484544 + <unknown>-12683 (-----) [005] .... 1920260.579430: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1299421 ofs=5230592 + <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1317097 ofs=5234688 + <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1441714 ofs=5238784 + <unknown>-12683 (-----) [005] .... 1920260.579438: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1081974 ofs=5242880 + <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1128684 ofs=5246976 + <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447381 ofs=5251072 + <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1466410 ofs=5255168 + <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1259909 ofs=5259264 + <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1125784 ofs=5263360 + <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1270592 ofs=5267456 + <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1246070 ofs=5271552 + <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1472544 ofs=5275648 + <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1113357 ofs=5279744 + <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1202021 ofs=5283840 + <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1078639 ofs=5287936 + <unknown>-12683 (-----) [005] .... 1920260.579449: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1176171 ofs=5292032 + <unknown>-12683 (-----) [005] .... 1920260.579450: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1089516 ofs=5296128 + <unknown>-12683 (-----) [005] .... 1920260.579451: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1400065 ofs=5300224 + <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1300489 ofs=5304320 + <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1452081 ofs=5308416 + <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1161862 ofs=5312512 + <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1161871 ofs=5316608 + <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1263798 ofs=5320704 + <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1126887 ofs=5324800 + <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1375498 ofs=5328896 + <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1328067 ofs=5332992 + <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1420691 ofs=5337088 + <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1298707 ofs=5341184 + <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1078670 ofs=5345280 + <unknown>-12683 (-----) [005] .... 1920260.579457: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1430498 ofs=5349376 + <unknown>-12683 (-----) [005] .... 1920260.579458: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1338720 ofs=5353472 + <unknown>-12683 (-----) [005] .... 1920260.579476: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1452611 ofs=5357568 + <unknown>-12683 (-----) [006] .... 1920260.580451: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1241967 ofs=0 + <unknown>-12683 (-----) [006] .... 1920260.580454: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1116541 ofs=4096 + <unknown>-12683 (-----) [006] .... 1920260.580461: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1145049 ofs=8192 + <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1277255 ofs=12288 + <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1098037 ofs=16384 + <unknown>-12683 (-----) [006] .... 1920260.580463: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1135986 ofs=20480 + <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1154455 ofs=24576 + <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1221822 ofs=28672 + <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1078684 ofs=32768 + <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1158876 ofs=36864 + <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1289644 ofs=40960 + <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1289386 ofs=45056 + <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1131002 ofs=49152 + <unknown>-12683 (-----) [006] .... 1920260.580467: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1464335 ofs=53248 + <unknown>-12683 (-----) [006] .... 1920260.580468: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1135789 ofs=57344 + <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1240897 ofs=61440 + <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1241770 ofs=65536 + <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1421959 ofs=69632 + <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1230007 ofs=73728 + <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1109271 ofs=77824 + <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1159974 ofs=81920 + <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1154528 ofs=86016 + <unknown>-12683 (-----) [006] .... 1920260.580472: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1315790 ofs=90112 + <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1185583 ofs=94208 + <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1253153 ofs=98304 + <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103982 ofs=102400 + <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1284589 ofs=106496 + <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1169601 ofs=110592 + <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1206248 ofs=114688 + <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1261161 ofs=118784 + <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1305841 ofs=122880 + <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1468293 ofs=126976 + <unknown>-12683 (-----) [004] .... 1920260.580646: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1318816 ofs=16384 + <unknown>-12683 (-----) [004] .... 1920260.580649: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1472922 ofs=20480 + <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1473229 ofs=24576 + <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1524262 ofs=28672 + <unknown>-12683 (-----) [004] .... 1920260.580656: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1205714 ofs=32768 + <unknown>-12683 (-----) [004] .... 1920260.580657: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1310560 ofs=36864 + <unknown>-12683 (-----) [004] .... 1920260.580658: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1295070 ofs=40960 + <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1404093 ofs=45056 + <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1435814 ofs=49152 + <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1435442 ofs=53248 + <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1096077 ofs=57344 + <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1483793 ofs=61440 + <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1231298 ofs=65536 + <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1215648 ofs=69632 + <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1327326 ofs=73728 + <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1108894 ofs=77824 + <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1327545 ofs=81920 + <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1328804 ofs=86016 + <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1300171 ofs=90112 + <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1353250 ofs=94208 + <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1333681 ofs=98304 + <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1144969 ofs=102400 + <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1450962 ofs=106496 + <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1255701 ofs=110592 + <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1294782 ofs=114688 + <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1226912 ofs=118784 + <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1294579 ofs=122880 + <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1246960 ofs=126976 + <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1199086 ofs=131072 + <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1449590 ofs=135168 + <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1276363 ofs=139264 + <unknown>-12683 (-----) [004] .... 1920260.580675: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1389998 ofs=143360 + <unknown>-12683 (-----) [004] .... 1920260.580739: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1423031 ofs=1249280 + <unknown>-12683 (-----) [004] .... 1920260.580741: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1171032 ofs=1253376 + <unknown>-12683 (-----) [004] .... 1920260.580742: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1320946 ofs=1257472 + <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1314696 ofs=1261568 + <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1414864 ofs=1265664 + <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1334933 ofs=1269760 + <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1242845 ofs=1273856 + <unknown>-12683 (-----) [004] .... 1920260.580747: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1289488 ofs=1277952 + <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1335445 ofs=1282048 + <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1289663 ofs=1286144 + <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1080462 ofs=1290240 + <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1286303 ofs=1294336 + <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1353531 ofs=1298432 + <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1280701 ofs=1302528 + <unknown>-12683 (-----) [004] .... 1920260.580751: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1107730 ofs=1306624 + <unknown>-12683 (-----) [004] .... 1920260.580752: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1242729 ofs=1310720 + <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1078336 ofs=1314816 + <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1372425 ofs=1318912 + <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1248813 ofs=1323008 + <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1201155 ofs=1327104 + <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1250103 ofs=1331200 + <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1359710 ofs=1335296 + <unknown>-12683 (-----) [004] .... 1920260.580756: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1272462 ofs=1339392 + <unknown>-12683 (-----) [004] .... 1920260.580758: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1097035 ofs=1343488 + <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1233124 ofs=1347584 + <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1455812 ofs=1351680 + <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1355689 ofs=1355776 + <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1263593 ofs=1359872 + <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1230789 ofs=1363968 + <unknown>-12683 (-----) [004] .... 1920260.580761: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1143766 ofs=1368064 + <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1269666 ofs=1372160 + <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1353022 ofs=1376256 + <unknown>-12683 (-----) [004] .... 1920260.581613: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1355509 ofs=258048 + <unknown>-12683 (-----) [004] .... 1920260.581615: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1178902 ofs=262144 + <unknown>-12683 (-----) [004] .... 1920260.581616: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1193649 ofs=266240 + <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1225497 ofs=270336 + <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1228259 ofs=274432 + <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1309674 ofs=278528 + <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1239390 ofs=282624 + <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1468083 ofs=286720 + <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1292751 ofs=290816 + <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1318066 ofs=294912 + <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1489314 ofs=299008 + <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1169867 ofs=303104 + <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1314256 ofs=307200 + <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1310230 ofs=311296 + <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1356180 ofs=315392 + <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1419179 ofs=319488 + <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1307265 ofs=323584 + <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1218590 ofs=327680 + <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447586 ofs=331776 + <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1209382 ofs=335872 + <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1072148 ofs=339968 + <unknown>-12683 (-----) [004] .... 1920260.581645: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1227195 ofs=344064 + <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1246369 ofs=348160 + <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1193845 ofs=352256 + <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1137553 ofs=356352 + <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1475215 ofs=360448 + <unknown>-12683 (-----) [004] .... 1920260.581648: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1258935 ofs=364544 + <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1448788 ofs=368640 + <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447611 ofs=372736 + <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1290842 ofs=376832 + <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1447826 ofs=380928 + <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino 55815 page=0000000000000000 pfn=1181016 ofs=385024 + <unknown>-12683 (-----) [005] .... 1920260.582230: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1216810 ofs=1662976 + <unknown>-12683 (-----) [005] .... 1920260.582234: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1175966 ofs=1667072 + <unknown>-12683 (-----) [005] .... 1920260.582235: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1449798 ofs=1671168 + <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1273480 ofs=1675264 + <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1152779 ofs=1679360 + <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1272810 ofs=1683456 + <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1248634 ofs=1687552 + <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1203376 ofs=1691648 + <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1138880 ofs=1695744 + <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1344591 ofs=1699840 + <unknown>-12683 (-----) [005] .... 1920260.582239: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1416060 ofs=1703936 + <unknown>-12683 (-----) [005] .... 1920260.582246: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1128676 ofs=1708032 + <unknown>-12683 (-----) [005] .... 1920260.582247: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1301921 ofs=1712128 + <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1384569 ofs=1716224 + <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1249106 ofs=1720320 + <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1206596 ofs=1724416 + <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1429831 ofs=1728512 + <unknown>-12683 (-----) [005] .... 1920260.582252: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1107796 ofs=1732608 + <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1098336 ofs=1736704 + <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1230286 ofs=1740800 + <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1100370 ofs=1744896 + <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1241930 ofs=1748992 + <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1366807 ofs=1753088 + <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1136252 ofs=1757184 + <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1274291 ofs=1761280 + <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1254775 ofs=1765376 + <unknown>-12683 (-----) [005] .... 1920260.582259: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1194679 ofs=1769472 + <unknown>-12683 (-----) [005] .... 1920260.582262: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1177090 ofs=1773568 + <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1343925 ofs=1777664 + <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1159217 ofs=1781760 + <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1435471 ofs=1785856 + <unknown>-12683 (-----) [005] .... 1920260.582264: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1435529 ofs=1789952 + <unknown>-12683 (-----) [004] .... 1920260.582524: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1181910 ofs=0 + <unknown>-12683 (-----) [004] .... 1920260.582528: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1212021 ofs=4096 + <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1162778 ofs=8192 + <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1107700 ofs=12288 + <unknown>-12683 (-----) [004] .... 1920260.583553: mm_filemap_add_to_page_cache: dev 0:64771 ino 57137 page=0000000000000000 pfn=1093394 ofs=3399680 + <unknown>-12683 (-----) [004] .... 1920260.583984: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1121431 ofs=242503680 + <unknown>-12683 (-----) [004] .... 1920260.583986: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1168551 ofs=13115392 + <unknown>-12683 (-----) [004] .... 1920260.584304: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1347409 ofs=0 + <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1428681 ofs=4096 + <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1259106 ofs=8192 + <unknown>-12683 (-----) [004] .... 1920260.584308: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1343229 ofs=12288 + <unknown>-12694 (-----) [005] .... 1920260.584622: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1098733 ofs=1531904 + <unknown>-12696 (-----) [006] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331319 ofs=1536000 + <unknown>-12694 (-----) [005] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1278537 ofs=1540096 + <unknown>-12696 (-----) [006] .... 1920260.584631: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1492534 ofs=1544192 + <unknown>-12694 (-----) [005] .... 1920260.584636: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1460878 ofs=1548288 + <unknown>-12694 (-----) [005] .... 1920260.584640: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092973 ofs=1552384 + <unknown>-12694 (-----) [005] .... 1920260.584641: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1103200 ofs=1556480 + <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1257426 ofs=1560576 + <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1219424 ofs=1564672 + <unknown>-12683 (-----) [004] .... 1920260.584660: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1279352 ofs=1568768 + <unknown>-12696 (-----) [006] .... 1920260.584662: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1260572 ofs=1572864 + <unknown>-12683 (-----) [004] .... 1920260.584663: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1225809 ofs=1576960 + <unknown>-12696 (-----) [006] .... 1920260.584665: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1350766 ofs=1585152 + <unknown>-12697 (-----) [007] .... 1920260.584666: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1107173 ofs=1581056 + <unknown>-12683 (-----) [004] .... 1920260.584668: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1305885 ofs=1589248 + <unknown>-12694 (-----) [005] .... 1920260.584669: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1293385 ofs=1593344 + <unknown>-12696 (-----) [006] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1173841 ofs=1597440 + <unknown>-12697 (-----) [007] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1080021 ofs=1601536 + <unknown>-12683 (-----) [004] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1147419 ofs=1605632 + <unknown>-12696 (-----) [006] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1252762 ofs=1609728 + <unknown>-12694 (-----) [005] .... 1920260.584674: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1323916 ofs=1613824 + <unknown>-12683 (-----) [004] .... 1920260.584675: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1155631 ofs=1617920 + <unknown>-12696 (-----) [006] .... 1920260.584676: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449815 ofs=1622016 + <unknown>-12694 (-----) [005] .... 1920260.584678: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1227069 ofs=1626112 + <unknown>-12696 (-----) [006] .... 1920260.584680: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1317692 ofs=1630208 + <unknown>-12694 (-----) [005] .... 1920260.584681: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1492244 ofs=1634304 + <unknown>-12683 (-----) [004] .... 1920260.584682: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241876 ofs=1638400 + <unknown>-12697 (-----) [007] .... 1920260.585446: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1402958 ofs=167936 + <unknown>-12697 (-----) [007] .... 1920260.585449: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1133263 ofs=172032 + <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1295502 ofs=176128 + <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1249495 ofs=180224 + <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1237999 ofs=184320 + <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1280965 ofs=188416 + <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1208361 ofs=192512 + <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1308840 ofs=196608 + <unknown>-12695 (-----) [004] .... 1920260.585455: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1138875 ofs=569344 + <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1314886 ofs=573440 + <unknown>-12697 (-----) [007] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242734 ofs=200704 + <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1447386 ofs=577536 + <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241302 ofs=204800 + <unknown>-12695 (-----) [004] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1328663 ofs=581632 + <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1476101 ofs=208896 + <unknown>-12695 (-----) [004] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1209461 ofs=585728 + <unknown>-12697 (-----) [007] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1080147 ofs=212992 + <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1128509 ofs=217088 + <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1371915 ofs=221184 + <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1264015 ofs=225280 + <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1211695 ofs=229376 + <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1150386 ofs=233472 + <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1135747 ofs=237568 + <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1128230 ofs=241664 + <unknown>-12697 (-----) [007] .... 1920260.585464: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1155451 ofs=245760 + <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1246841 ofs=249856 + <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1462971 ofs=253952 + <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1131333 ofs=258048 + <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289407 ofs=262144 + <unknown>-12695 (-----) [004] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1134730 ofs=589824 + <unknown>-12697 (-----) [007] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289873 ofs=266240 + <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1448734 ofs=270336 + <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1129776 ofs=593920 + <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1524090 ofs=274432 + <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1399725 ofs=598016 + <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1524081 ofs=278528 + <unknown>-12695 (-----) [004] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1276535 ofs=602112 + <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1524060 ofs=282624 + <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449847 ofs=606208 + <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1158944 ofs=286720 + <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1384536 ofs=610304 + <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1116785 ofs=290816 + <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1308118 ofs=614400 + <unknown>-12697 (-----) [007] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1448669 ofs=294912 + <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1227050 ofs=618496 + <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289324 ofs=622592 + <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1187869 ofs=626688 + <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1400523 ofs=630784 + <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1344176 ofs=634880 + <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092871 ofs=638976 + <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092021 ofs=643072 + <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1198169 ofs=647168 + <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1371540 ofs=651264 + <unknown>-12683 (-----) [005] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1195003 ofs=348160 + <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1228787 ofs=655360 + <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1236123 ofs=659456 + <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1137213 ofs=663552 + <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1294618 ofs=667648 + <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241048 ofs=671744 + <unknown>-12695 (-----) [004] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1228779 ofs=675840 + <unknown>-12683 (-----) [005] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1199292 ofs=352256 + <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1200861 ofs=356352 + <unknown>-12695 (-----) [004] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1309572 ofs=679936 + <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1215770 ofs=360448 + <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1409002 ofs=684032 + <unknown>-12683 (-----) [005] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1151883 ofs=364544 + <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1103729 ofs=688128 + <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1468126 ofs=368640 + <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1162720 ofs=692224 + <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1251672 ofs=372736 + <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1199221 ofs=696320 + <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1283325 ofs=376832 + <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1190489 ofs=380928 + <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1489117 ofs=385024 + <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1273899 ofs=389120 + <unknown>-12683 (-----) [005] .... 1920260.585485: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1274459 ofs=393216 + <unknown>-12683 (-----) [005] .... 1920260.585486: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1316649 ofs=397312 + <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1375678 ofs=401408 + <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1483317 ofs=405504 + <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1240286 ofs=409600 + <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1131345 ofs=413696 + <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1200483 ofs=417792 + <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1384693 ofs=421888 + <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1161385 ofs=425984 + <unknown>-12683 (-----) [005] .... 1920260.585494: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1452025 ofs=430080 + <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1253654 ofs=434176 + <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1116697 ofs=438272 + <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1432645 ofs=442368 + <unknown>-12694 (-----) [006] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1337397 ofs=16384 + <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1304229 ofs=446464 + <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1419147 ofs=450560 + <unknown>-12683 (-----) [005] .... 1920260.585498: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1349246 ofs=454656 + <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1128519 ofs=458752 + <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1125168 ofs=462848 + <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1081031 ofs=20480 + <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1293022 ofs=24576 + <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1113007 ofs=28672 + <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1339312 ofs=32768 + <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1412311 ofs=36864 + <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1260960 ofs=40960 + <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189529 ofs=45056 + <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1412184 ofs=49152 + <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1481227 ofs=53248 + <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1455940 ofs=57344 + <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1299132 ofs=61440 + <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1337375 ofs=65536 + <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1328742 ofs=69632 + <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1315646 ofs=73728 + <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1225475 ofs=77824 + <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1146097 ofs=81920 + <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1318775 ofs=86016 + <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1448391 ofs=90112 + <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1441412 ofs=94208 + <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1138111 ofs=98304 + <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1143223 ofs=102400 + <unknown>-12683 (-----) [005] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1079876 ofs=466944 + <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1447637 ofs=106496 + <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1220585 ofs=110592 + <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449051 ofs=114688 + <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1313180 ofs=118784 + <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1313166 ofs=122880 + <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1313154 ofs=126976 + <unknown>-12683 (-----) [005] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1218394 ofs=471040 + <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1144047 ofs=131072 + <unknown>-12683 (-----) [005] .... 1920260.585537: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1218579 ofs=475136 + <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1241332 ofs=135168 + <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1097199 ofs=139264 + <unknown>-12694 (-----) [006] .... 1920260.585545: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1214197 ofs=143360 + <unknown>-12694 (-----) [006] .... 1920260.585645: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1197633 ofs=147456 + <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1311536 ofs=151552 + <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1322952 ofs=155648 + <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1346974 ofs=159744 + <unknown>-12694 (-----) [006] .... 1920260.585648: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1257232 ofs=163840 + <unknown>-12695 (-----) [004] .... 1920260.586355: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1204484 ofs=700416 + <unknown>-12695 (-----) [004] .... 1920260.586357: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1326426 ofs=704512 + <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1151808 ofs=708608 + <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1209422 ofs=712704 + <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1408387 ofs=716800 + <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1197336 ofs=720896 + <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1205652 ofs=724992 + <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1133421 ofs=729088 + <unknown>-12695 (-----) [004] .... 1920260.586364: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092173 ofs=733184 + <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1124430 ofs=737280 + <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1143926 ofs=741376 + <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1090109 ofs=745472 + <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1102012 ofs=749568 + <unknown>-12695 (-----) [004] .... 1920260.586367: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1154930 ofs=753664 + <unknown>-12695 (-----) [004] .... 1920260.586368: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1132993 ofs=757760 + <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1430780 ofs=761856 + <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1197452 ofs=765952 + <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1075111 ofs=770048 + <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1275616 ofs=774144 + <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1444981 ofs=778240 + <unknown>-12695 (-----) [004] .... 1920260.586371: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1452592 ofs=782336 + <unknown>-12695 (-----) [004] .... 1920260.586374: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1102857 ofs=786432 + <unknown>-12695 (-----) [004] .... 1920260.586376: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1406969 ofs=790528 + <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1522553 ofs=794624 + <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1260771 ofs=798720 + <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1474649 ofs=802816 + <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1268708 ofs=806912 + <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1346144 ofs=811008 + <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1081167 ofs=815104 + <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1137677 ofs=819200 + <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1161175 ofs=823296 + <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1461331 ofs=827392 + <unknown>-12695 (-----) [004] .... 1920260.586492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1347219 ofs=831488 + <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1290004 ofs=835584 + <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1299174 ofs=839680 + <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1317595 ofs=843776 + <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1484924 ofs=847872 + <unknown>-12695 (-----) [004] .... 1920260.586497: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1169920 ofs=851968 + <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1359189 ofs=856064 + <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1307842 ofs=860160 + <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1237858 ofs=864256 + <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189461 ofs=868352 + <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1223232 ofs=872448 + <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1104076 ofs=876544 + <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1079223 ofs=880640 + <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1092537 ofs=884736 + <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1353960 ofs=888832 + <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1346330 ofs=892928 + <unknown>-12695 (-----) [004] .... 1920260.586506: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1345764 ofs=897024 + <unknown>-12695 (-----) [004] .... 1920260.586507: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1363913 ofs=901120 + <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1319570 ofs=905216 + <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1367024 ofs=909312 + <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1333808 ofs=913408 + <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1158627 ofs=917504 + <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1300368 ofs=921600 + <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1245363 ofs=925696 + <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1345609 ofs=929792 + <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1393826 ofs=933888 + <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1200552 ofs=937984 + <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1170885 ofs=942080 + <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1536209 ofs=946176 + <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189630 ofs=950272 + <unknown>-12695 (-----) [004] .... 1920260.586513: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1121010 ofs=954368 + <unknown>-12695 (-----) [004] .... 1920260.586514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1324474 ofs=958464 + <unknown>-12697 (-----) [007] .... 1920260.586578: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1129628 ofs=299008 + <unknown>-12697 (-----) [007] .... 1920260.586579: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1307120 ofs=303104 + <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1347284 ofs=307200 + <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1312996 ofs=311296 + <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1170623 ofs=315392 + <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1359281 ofs=319488 + <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1180021 ofs=323584 + <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1195728 ofs=327680 + <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1163642 ofs=331776 + <unknown>-12697 (-----) [007] .... 1920260.586587: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1152538 ofs=335872 + <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1345922 ofs=339968 + <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1343604 ofs=344064 + <unknown>-12697 (-----) [007] .... 1920260.586721: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1399371 ofs=479232 + <unknown>-12697 (-----) [007] .... 1920260.586723: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1106549 ofs=483328 + <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331546 ofs=487424 + <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1299299 ofs=491520 + <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1288883 ofs=495616 + <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1399049 ofs=499712 + <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1146931 ofs=503808 + <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1296592 ofs=507904 + <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1468397 ofs=512000 + <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1215698 ofs=516096 + <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1177341 ofs=520192 + <unknown>-12697 (-----) [007] .... 1920260.586731: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1189162 ofs=524288 + <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1435997 ofs=528384 + <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1209896 ofs=532480 + <unknown>-12697 (-----) [007] .... 1920260.586733: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1255888 ofs=536576 + <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1234200 ofs=540672 + <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1422854 ofs=544768 + <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1435794 ofs=548864 + <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1236279 ofs=552960 + <unknown>-12697 (-----) [007] .... 1920260.586736: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1485732 ofs=557056 + <unknown>-12683 (-----) [005] .... 1920260.586743: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1417198 ofs=561152 + <unknown>-12683 (-----) [005] .... 1920260.586746: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1469450 ofs=565248 + <unknown>-12696 (-----) [004] .... 1920260.587465: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1489023 ofs=1040384 + <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1449498 ofs=1044480 + <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1447737 ofs=1048576 + <unknown>-12696 (-----) [004] .... 1920260.587470: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1124530 ofs=1052672 + <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1246743 ofs=1056768 + <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1441927 ofs=1060864 + <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1280581 ofs=1064960 + <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1289438 ofs=1069056 + <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1464236 ofs=1073152 + <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1125808 ofs=1077248 + <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1329385 ofs=1081344 + <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1314093 ofs=1085440 + <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1201837 ofs=1089536 + <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1327734 ofs=1093632 + <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1406568 ofs=1097728 + <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331873 ofs=1101824 + <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331898 ofs=1105920 + <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1331917 ofs=1110016 + <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1332091 ofs=1114112 + <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1108186 ofs=1118208 + <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1182631 ofs=1122304 + <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1085941 ofs=1126400 + <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1433982 ofs=1130496 + <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1387028 ofs=1134592 + <unknown>-12696 (-----) [004] .... 1920260.587488: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1353117 ofs=1138688 + <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1352364 ofs=1142784 + <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1144513 ofs=1146880 + <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1403984 ofs=1150976 + <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1278970 ofs=1155072 + <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1326743 ofs=1159168 + <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1221809 ofs=1163264 + <unknown>-12696 (-----) [004] .... 1920260.587492: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1268668 ofs=1167360 + <unknown>-12695 (-----) [005] .... 1920260.587502: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1074544 ofs=962560 + <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1074294 ofs=966656 + <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1075097 ofs=970752 + <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1162407 ofs=974848 + <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1141370 ofs=978944 + <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306487 ofs=983040 + <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306434 ofs=987136 + <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306347 ofs=991232 + <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306247 ofs=995328 + <unknown>-12695 (-----) [005] .... 1920260.587515: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306195 ofs=999424 + <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1306039 ofs=1003520 + <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1305983 ofs=1007616 + <unknown>-12694 (-----) [006] .... 1920260.587701: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1216391 ofs=1171456 + <unknown>-12694 (-----) [006] .... 1920260.587705: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1262462 ofs=1175552 + <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1358114 ofs=1179648 + <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1357898 ofs=1183744 + <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1237003 ofs=1187840 + <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1126319 ofs=1191936 + <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1415489 ofs=1196032 + <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1279558 ofs=1200128 + <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1434022 ofs=1204224 + <unknown>-12694 (-----) [006] .... 1920260.587709: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1220130 ofs=1208320 + <unknown>-12694 (-----) [006] .... 1920260.587710: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1163037 ofs=1212416 + <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1404501 ofs=1216512 + <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1406287 ofs=1220608 + <unknown>-12697 (-----) [007] .... 1920260.588132: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1355143 ofs=1376256 + <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1213923 ofs=1380352 + <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1243190 ofs=1384448 + <unknown>-12697 (-----) [007] .... 1920260.588143: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1300698 ofs=1388544 + <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1482568 ofs=1392640 + <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1461789 ofs=1396736 + <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242314 ofs=1400832 + <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1471996 ofs=1404928 + <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242742 ofs=1409024 + <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242579 ofs=1413120 + <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1242553 ofs=1417216 + <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1457332 ofs=1421312 + <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1315431 ofs=1425408 + <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1080653 ofs=1429504 + <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1324174 ofs=1433600 + <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1324142 ofs=1437696 + <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1157760 ofs=1441792 + <unknown>-12697 (-----) [007] .... 1920260.588151: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1075059 ofs=1445888 + <unknown>-12683 (-----) [006] .... 1920260.589785: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1279192 ofs=1486848 + <unknown>-12683 (-----) [006] .... 1920260.589790: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1278527 ofs=1490944 + <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1091778 ofs=1495040 + <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1339447 ofs=1499136 + <unknown>-12683 (-----) [006] .... 1920260.589792: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1254007 ofs=1503232 + <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1115173 ofs=1507328 + <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1393985 ofs=1511424 + <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1369123 ofs=1515520 + <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1314257 ofs=1519616 + <unknown>-12683 (-----) [006] .... 1920260.589802: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1404487 ofs=1523712 + <unknown>-12683 (-----) [006] .... 1920260.589803: mm_filemap_add_to_page_cache: dev 0:64771 ino 59205 page=0000000000000000 pfn=1354554 ofs=1527808 + <unknown>-12683 (-----) [006] .... 1920260.594312: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1141445 ofs=9801728 + <unknown>-12683 (-----) [006] .... 1920260.594322: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323774 ofs=231460864 + <unknown>-12683 (-----) [006] .... 1920260.594326: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323772 ofs=10993664 + <unknown>-12683 (-----) [006] .... 1920260.595212: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481305 ofs=9805824 + <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481306 ofs=9809920 + <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481316 ofs=9814016 + <unknown>-12683 (-----) [006] .... 1920260.595215: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1481340 ofs=9818112 + <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1394587 ofs=9822208 + <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103455 ofs=9826304 + <unknown>-12683 (-----) [006] .... 1920260.595217: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103271 ofs=9830400 + <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103168 ofs=9834496 + <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103145 ofs=9838592 + <unknown>-12683 (-----) [006] .... 1920260.595219: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103115 ofs=9842688 + <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103057 ofs=9846784 + <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1331958 ofs=9850880 + <unknown>-12683 (-----) [006] .... 1920260.595227: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1356305 ofs=9854976 + <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103708 ofs=9859072 + <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1099286 ofs=9863168 + <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1435190 ofs=9867264 + <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1395504 ofs=9871360 + <unknown>-12683 (-----) [006] .... 1920260.595230: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1352916 ofs=9875456 + <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1255529 ofs=9879552 + <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1336145 ofs=9883648 + <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1334143 ofs=9887744 + <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1328548 ofs=9891840 + <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1222215 ofs=9895936 + <unknown>-12683 (-----) [006] .... 1920260.595233: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1461056 ofs=9900032 + <unknown>-12683 (-----) [006] .... 1920260.595234: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1228276 ofs=9904128 + <unknown>-12683 (-----) [006] .... 1920260.595235: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1151188 ofs=9908224 + <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1443605 ofs=9912320 + <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1146821 ofs=9916416 + <unknown>-12683 (-----) [006] .... 1920260.595237: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103669 ofs=9920512 + <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103744 ofs=9924608 + <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1103868 ofs=9928704 + <unknown>-12683 (-----) [006] .... 1920260.595789: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1465942 ofs=15855616 + <unknown>-12683 (-----) [006] .... 1920260.595792: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323712 ofs=261189632 + <unknown>-12683 (-----) [006] .... 1920260.595998: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323701 ofs=262094848 + <unknown>-12683 (-----) [006] .... 1920260.596191: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1222287 ofs=15859712 + <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1213146 ofs=15863808 + <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1310396 ofs=15867904 + <unknown>-12683 (-----) [006] .... 1920260.596193: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1310177 ofs=15872000 + <unknown>-12683 (-----) [006] .... 1920260.596194: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1187914 ofs=15876096 + <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1322409 ofs=15880192 + <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1282484 ofs=15884288 + <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1097245 ofs=15888384 + <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1416816 ofs=15892480 + <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1257125 ofs=15896576 + <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1403527 ofs=15900672 + <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1218006 ofs=15904768 + <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1153893 ofs=15908864 + <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1328023 ofs=15912960 + <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1465412 ofs=15917056 + <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1092448 ofs=15921152 + <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1239220 ofs=15925248 + <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1276491 ofs=15929344 + <unknown>-12683 (-----) [006] .... 1920260.596205: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1262240 ofs=15933440 + <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1323793 ofs=15937536 + <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1074937 ofs=15941632 + <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1311157 ofs=15945728 + <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1308442 ofs=15949824 + <unknown>-12683 (-----) [006] .... 1920260.596210: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1467709 ofs=15953920 + <unknown>-12683 (-----) [006] .... 1920260.596211: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1394299 ofs=15958016 + <unknown>-12683 (-----) [004] .... 1920260.612586: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1316156 ofs=344064 + <unknown>-12683 (-----) [004] .... 1920260.612591: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1406323 ofs=348160 + <unknown>-12683 (-----) [004] .... 1920260.612601: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1216972 ofs=352256 + <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1271924 ofs=356352 + <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1369225 ofs=360448 + <unknown>-12683 (-----) [004] .... 1920260.612608: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1318474 ofs=364544 + <unknown>-12683 (-----) [004] .... 1920260.612609: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1227283 ofs=368640 + <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1364376 ofs=372736 + <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 6154 page=0000000000000000 pfn=1073400 ofs=376832 diff --git a/startop/scripts/lib/cmd_utils.py b/startop/scripts/lib/cmd_utils.py index bc5ca3140d3d..6071f145fe1d 100644 --- a/startop/scripts/lib/cmd_utils.py +++ b/startop/scripts/lib/cmd_utils.py @@ -26,6 +26,18 @@ import lib.print_utils as print_utils TIMEOUT = 50 SIMULATE = False +def run_command_nofail(cmd: List[str], **kwargs) -> None: + """Runs cmd list with default timeout. + + Throws exception if the execution fails. + """ + my_kwargs = {"timeout": TIMEOUT, "shell": False, "simulate": False} + my_kwargs.update(kwargs) + passed, out = execute_arbitrary_command(cmd, **my_kwargs) + if not passed: + raise RuntimeError( + "Failed to execute %s (kwargs=%s), output=%s" % (cmd, kwargs, out)) + def run_adb_shell_command(cmd: str) -> Tuple[bool, str]: """Runs command using adb shell. diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc index 6047e8c74e38..09f9c04d9e2c 100644 --- a/startop/view_compiler/dex_builder.cc +++ b/startop/view_compiler/dex_builder.cc @@ -102,6 +102,12 @@ std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) { case Instruction::Op::kCheckCast: out << "kCheckCast"; return out; + case Instruction::Op::kGetStaticField: + out << "kGetStaticField"; + return out; + case Instruction::Op::kSetStaticField: + out << "kSetStaticField"; + return out; } } @@ -229,6 +235,22 @@ ir::Type* DexBuilder::GetOrAddType(const std::string& descriptor) { return type; } +ir::FieldDecl* DexBuilder::GetOrAddField(TypeDescriptor parent, const std::string& name, + TypeDescriptor type) { + const auto key = std::make_tuple(parent, name); + if (field_decls_by_key_.find(key) != field_decls_by_key_.end()) { + return field_decls_by_key_[key]; + } + + ir::FieldDecl* field = Alloc<ir::FieldDecl>(); + field->parent = GetOrAddType(parent); + field->name = GetOrAddString(name); + field->type = GetOrAddType(type); + dex_file_->fields_map[field->orig_index] = field; + field_decls_by_key_[key] = field; + return field; +} + ir::Proto* Prototype::Encode(DexBuilder* dex) const { auto* proto = dex->Alloc<ir::Proto>(); proto->shorty = dex->GetOrAddString(Shorty()); @@ -360,6 +382,9 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) { return EncodeNew(instruction); case Instruction::Op::kCheckCast: return EncodeCast(instruction); + case Instruction::Op::kGetStaticField: + case Instruction::Op::kSetStaticField: + return EncodeStaticFieldOp(instruction); } } @@ -428,7 +453,7 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct // first move all the arguments into contiguous temporary registers. std::array<Value, kMaxArgs> scratch = GetScratchRegisters<kMaxArgs>(); - const auto& prototype = dex_->GetPrototypeByMethodId(instruction.method_id()); + const auto& prototype = dex_->GetPrototypeByMethodId(instruction.index_argument()); CHECK(prototype.has_value()); for (size_t i = 0; i < instruction.args().size(); ++i) { @@ -452,12 +477,12 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct Encode3rc(InvokeToInvokeRange(opcode), instruction.args().size(), - instruction.method_id(), + instruction.index_argument(), RegisterValue(scratch[0])); } else { Encode35c(opcode, instruction.args().size(), - instruction.method_id(), + instruction.index_argument(), arguments[0], arguments[1], arguments[2], @@ -514,6 +539,35 @@ void MethodBuilder::EncodeCast(const Instruction& instruction) { Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value()); } +void MethodBuilder::EncodeStaticFieldOp(const Instruction& instruction) { + switch (instruction.opcode()) { + case Instruction::Op::kGetStaticField: { + CHECK(instruction.dest().has_value()); + CHECK(instruction.dest()->is_variable()); + CHECK_EQ(0, instruction.args().size()); + + Encode21c(::art::Instruction::SGET, + RegisterValue(*instruction.dest()), + instruction.index_argument()); + break; + } + case Instruction::Op::kSetStaticField: { + CHECK(!instruction.dest().has_value()); + const auto& args = instruction.args(); + CHECK_EQ(1, args.size()); + CHECK(args[0].is_variable()); + + Encode21c(::art::Instruction::SPUT, + RegisterValue(args[0]), + instruction.index_argument()); + break; + } + default: { + LOG(FATAL) << "Unsupported static field operation"; + } + } +} + size_t MethodBuilder::RegisterValue(const Value& value) const { if (value.is_register()) { return value.value(); diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h index 541d80077bd3..3f9ac43ae532 100644 --- a/startop/view_compiler/dex_builder.h +++ b/startop/view_compiler/dex_builder.h @@ -153,6 +153,7 @@ class Instruction { kBranchEqz, kBranchNEqz, kCheckCast, + kGetStaticField, kInvokeDirect, kInvokeInterface, kInvokeStatic, @@ -162,6 +163,7 @@ class Instruction { kNew, kReturn, kReturnObject, + kSetStaticField }; //////////////////////// @@ -170,12 +172,12 @@ class Instruction { // For instructions with no return value and no arguments. static inline Instruction OpNoArgs(Op opcode) { - return Instruction{opcode, /*method_id*/ 0, /*dest*/ {}}; + return Instruction{opcode, /*index_argument*/ 0, /*dest*/ {}}; } // For most instructions, which take some number of arguments and have an optional return value. template <typename... T> static inline Instruction OpWithArgs(Op opcode, std::optional<const Value> dest, T... args) { - return Instruction{opcode, /*method_id=*/0, /*result_is_object=*/false, dest, args...}; + return Instruction{opcode, /*index_argument=*/0, /*result_is_object=*/false, dest, args...}; } // A cast instruction. Basically, `(type)val` @@ -186,77 +188,87 @@ class Instruction { // For method calls. template <typename... T> - static inline Instruction InvokeVirtual(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeVirtual(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeVirtual, method_id, /*result_is_object=*/false, dest, this_arg, args...}; + Op::kInvokeVirtual, index_argument, /*result_is_object=*/false, dest, this_arg, args...}; } // Returns an object template <typename... T> - static inline Instruction InvokeVirtualObject(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeVirtualObject(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeVirtual, method_id, /*result_is_object=*/true, dest, this_arg, args...}; + Op::kInvokeVirtual, index_argument, /*result_is_object=*/true, dest, this_arg, args...}; } // For direct calls (basically, constructors). template <typename... T> - static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeDirect(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeDirect, method_id, /*result_is_object=*/false, dest, this_arg, args...}; + Op::kInvokeDirect, index_argument, /*result_is_object=*/false, dest, this_arg, args...}; } // Returns an object template <typename... T> - static inline Instruction InvokeDirectObject(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeDirectObject(size_t index_argument, std::optional<const Value> dest, Value this_arg, T... args) { return Instruction{ - Op::kInvokeDirect, method_id, /*result_is_object=*/true, dest, this_arg, args...}; + Op::kInvokeDirect, index_argument, /*result_is_object=*/true, dest, this_arg, args...}; } // For static calls. template <typename... T> - static inline Instruction InvokeStatic(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeStatic(size_t index_argument, std::optional<const Value> dest, T... args) { - return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/false, dest, args...}; + return Instruction{Op::kInvokeStatic, index_argument, /*result_is_object=*/false, dest, args...}; } // Returns an object template <typename... T> - static inline Instruction InvokeStaticObject(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeStaticObject(size_t index_argument, std::optional<const Value> dest, T... args) { - return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/true, dest, args...}; + return Instruction{Op::kInvokeStatic, index_argument, /*result_is_object=*/true, dest, args...}; } // For static calls. template <typename... T> - static inline Instruction InvokeInterface(size_t method_id, std::optional<const Value> dest, + static inline Instruction InvokeInterface(size_t index_argument, std::optional<const Value> dest, T... args) { - return Instruction{Op::kInvokeInterface, method_id, /*result_is_object=*/false, dest, args...}; + return Instruction{Op::kInvokeInterface, index_argument, /*result_is_object=*/false, dest, args...}; + + } + + static inline Instruction GetStaticField(size_t field_id, Value dest) { + return Instruction{Op::kGetStaticField, field_id, dest}; + } + + static inline Instruction SetStaticField(size_t field_id, Value value) { + return Instruction{Op::kSetStaticField, field_id, /*result_is_object=*/false, /*dest=*/{}, value}; } + /////////////// // Accessors // /////////////// Op opcode() const { return opcode_; } - size_t method_id() const { return method_id_; } + size_t index_argument() const { return index_argument_; } bool result_is_object() const { return result_is_object_; } const std::optional<const Value>& dest() const { return dest_; } const std::vector<const Value>& args() const { return args_; } private: - inline Instruction(Op opcode, size_t method_id, std::optional<const Value> dest) - : opcode_{opcode}, method_id_{method_id}, result_is_object_{false}, dest_{dest}, args_{} {} + inline Instruction(Op opcode, size_t index_argument, std::optional<const Value> dest) + : opcode_{opcode}, index_argument_{index_argument}, result_is_object_{false}, dest_{dest}, args_{} {} template <typename... T> - inline constexpr Instruction(Op opcode, size_t method_id, bool result_is_object, + inline constexpr Instruction(Op opcode, size_t index_argument, bool result_is_object, std::optional<const Value> dest, T... args) : opcode_{opcode}, - method_id_{method_id}, + index_argument_{index_argument}, result_is_object_{result_is_object}, dest_{dest}, args_{args...} {} const Op opcode_; // The index of the method to invoke, for kInvokeVirtual and similar opcodes. - const size_t method_id_{0}; + const size_t index_argument_{0}; const bool result_is_object_; const std::optional<const Value> dest_; const std::vector<const Value> args_; @@ -319,6 +331,7 @@ class MethodBuilder { void EncodeBranch(art::Instruction::Code op, const Instruction& instruction); void EncodeNew(const Instruction& instruction); void EncodeCast(const Instruction& instruction); + void EncodeStaticFieldOp(const Instruction& instruction); // Low-level instruction format encoding. See // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of @@ -481,6 +494,11 @@ class DexBuilder { // See the TypeDescriptor class for help generating these. GetOrAddType can be used to declare // imported classes. ir::Type* GetOrAddType(const std::string& descriptor); + inline ir::Type* GetOrAddType(TypeDescriptor descriptor) { + return GetOrAddType(descriptor.descriptor()); + } + + ir::FieldDecl* GetOrAddField(TypeDescriptor parent, const std::string& name, TypeDescriptor type); // Returns the method id for the method, creating it if it has not been created yet. const MethodDeclData& GetOrDeclareMethod(TypeDescriptor type, const std::string& name, @@ -526,6 +544,9 @@ class DexBuilder { // Keep track of already-encoded protos. std::map<Prototype, ir::Proto*> proto_map_; + + // Keep track of fields that have been declared + std::map<std::tuple<TypeDescriptor, std::string>, ir::FieldDecl*> field_decls_by_key_; }; template <typename... T> diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp index 22a3cfafbc44..1214538e8f0d 100644 --- a/startop/view_compiler/dex_builder_test/Android.bp +++ b/startop/view_compiler/dex_builder_test/Android.bp @@ -39,6 +39,7 @@ android_test { srcs: [ "src/android/startop/test/DexBuilderTest.java", "src/android/startop/test/LayoutCompilerTest.java", + "src/android/startop/test/TestClass.java", ], sdk_version: "current", data: [":generate_dex_testcases", ":generate_compiled_layout1", ":generate_compiled_layout2"], diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java index f7b1674894f5..6c0b8bbe8b83 100644 --- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java +++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java @@ -24,10 +24,10 @@ import java.lang.reflect.Method; // Adding tests here requires changes in several other places. See README.md in // the view_compiler directory for more information. -public class DexBuilderTest { +public final class DexBuilderTest { static ClassLoader loadDexFile(String filename) throws Exception { return new PathClassLoader("/data/local/tmp/dex-builder-test/" + filename, - ClassLoader.getSystemClassLoader()); + DexBuilderTest.class.getClassLoader()); } public void hello() {} @@ -167,4 +167,23 @@ public class DexBuilderTest { } Assert.assertTrue(castFailed); } + + @Test + public void readStaticField() throws Exception { + ClassLoader loader = loadDexFile("simple.dex"); + Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests"); + Method method = clazz.getMethod("readStaticField"); + TestClass.staticInteger = 5; + Assert.assertEquals(5, method.invoke(null)); + } + + @Test + public void setStaticField() throws Exception { + ClassLoader loader = loadDexFile("simple.dex"); + Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests"); + Method method = clazz.getMethod("setStaticField"); + TestClass.staticInteger = 5; + method.invoke(null); + Assert.assertEquals(7, TestClass.staticInteger); + } } diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/TestClass.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/TestClass.java new file mode 100644 index 000000000000..dd7792306030 --- /dev/null +++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/TestClass.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package android.startop.test; + + /** + * A simple class to help test DexBuilder. + */ +public final class TestClass { + public static int staticInteger; + + public int instanceField; +} diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc index f62ec5dde85e..fee5e722bc55 100644 --- a/startop/view_compiler/dex_testcase_generator.cc +++ b/startop/view_compiler/dex_testcase_generator.cc @@ -282,6 +282,37 @@ void GenerateSimpleTestCases(const string& outdir) { method.Encode(); }(castObjectToString); + // Read a static field + // integer readStaticField() { return TestClass.staticInteger; } + MethodBuilder readStaticField{ + cbuilder.CreateMethod("readStaticField", Prototype{TypeDescriptor::Int()})}; + [&](MethodBuilder& method) { + const ir::FieldDecl* field = + dex_file.GetOrAddField(TypeDescriptor::FromClassname("android.startop.test.TestClass"), + "staticInteger", + TypeDescriptor::Int()); + Value result{method.MakeRegister()}; + method.AddInstruction(Instruction::GetStaticField(field->orig_index, result)); + method.BuildReturn(result, /*is_object=*/false); + method.Encode(); + }(readStaticField); + + // Set a static field + // void setStaticField() { TestClass.staticInteger = 7; } + MethodBuilder setStaticField{ + cbuilder.CreateMethod("setStaticField", Prototype{TypeDescriptor::Void()})}; + [&](MethodBuilder& method) { + const ir::FieldDecl* field = + dex_file.GetOrAddField(TypeDescriptor::FromClassname("android.startop.test.TestClass"), + "staticInteger", + TypeDescriptor::Int()); + Value number{method.MakeRegister()}; + method.BuildConst4(number, 7); + method.AddInstruction(Instruction::SetStaticField(field->orig_index, number)); + method.BuildReturn(); + method.Encode(); + }(setStaticField); + slicer::MemView image{dex_file.CreateImage()}; std::ofstream out_file(outdir + "/simple.dex"); out_file.write(image.ptr<const char>(), image.size()); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 91bea5ff479b..4016c5c6c6f3 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3029,6 +3029,23 @@ public class CarrierConfigManager { "is_opportunistic_subscription_bool"; /** + * Configs used by the IMS stack. + */ + public static final class Ims { + /** Prefix of all Ims.KEY_* constants. */ + public static final String KEY_PREFIX = "ims."; + + //TODO: Add configs related to IMS. + + private Ims() {} + + private static PersistableBundle getDefaults() { + PersistableBundle defaults = new PersistableBundle(); + return defaults; + } + } + + /** * A list of 4 GSM RSSI thresholds above which a signal level is considered POOR, * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting. * @@ -3463,6 +3480,7 @@ public class CarrierConfigManager { -89, /* SIGNAL_STRENGTH_GREAT */ }); sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true); + sDefaults.putAll(Ims.getDefaults()); } /** @@ -3659,4 +3677,75 @@ public class CarrierConfigManager { return ICarrierConfigLoader.Stub .asInterface(ServiceManager.getService(Context.CARRIER_CONFIG_SERVICE)); } + + /** + * Gets the configuration values for a component using its prefix. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * + * @param prefix prefix of the component. + * @param subId the subscription ID, normally obtained from {@link SubscriptionManager}. + * + * @see #getConfigForSubId + */ + @Nullable + public PersistableBundle getConfigByComponentForSubId(String prefix, int subId) { + PersistableBundle configs = getConfigForSubId(subId); + + if (configs == null) { + return null; + } + + PersistableBundle ret = new PersistableBundle(); + for (String configKey : configs.keySet()) { + if (configKey.startsWith(prefix)) { + addConfig(configKey, configs.get(configKey), ret); + } + } + + return ret; + } + + private void addConfig(String key, Object value, PersistableBundle configs) { + if (value instanceof String) { + configs.putString(key, (String) value); + } + + if (value instanceof String[]) { + configs.putStringArray(key, (String[]) value); + } + + if (value instanceof Integer) { + configs.putInt(key, (Integer) value); + } + + if (value instanceof Long) { + configs.putLong(key, (Long) value); + } + + if (value instanceof Double) { + configs.putDouble(key, (Double) value); + } + + if (value instanceof Boolean) { + configs.putBoolean(key, (Boolean) value); + } + + if (value instanceof int[]) { + configs.putIntArray(key, (int[]) value); + } + + if (value instanceof double[]) { + configs.putDoubleArray(key, (double[]) value); + } + + if (value instanceof boolean[]) { + configs.putBooleanArray(key, (boolean[]) value); + } + + if (value instanceof long[]) { + configs.putLongArray(key, (long[]) value); + } + } } diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java index 9d732baf7514..fb16d540fbb4 100644 --- a/telephony/java/android/telephony/CellSignalStrengthGsm.java +++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java @@ -143,7 +143,7 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P } /** - * Get the signal strength as dBm + * Get the signal strength as dBm. */ @Override public int getDbm() { @@ -163,18 +163,17 @@ public final class CellSignalStrengthGsm extends CellSignalStrength implements P } /** - * Return the Received Signal Strength Indicator + * Return the Received Signal Strength Indicator. * * @return the RSSI in dBm (-113, -51) or * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}. - * @hide */ public int getRssi() { return mRssi; } /** - * Return the Bit Error Rate + * Return the Bit Error Rate. * * @return the bit error rate (0-7, 99) as defined in TS 27.007 8.5 or * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}. diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java index 8c686f704967..8e1324b3be0b 100644 --- a/telephony/java/android/telephony/ims/ImsException.java +++ b/telephony/java/android/telephony/ims/ImsException.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.pm.PackageManager; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import java.lang.annotation.Retention; @@ -55,12 +56,23 @@ public final class ImsException extends Exception { */ public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; + /** + * The subscription ID associated with this operation is invalid or not active. + * <p> + * This is a configuration error and there should be no retry. The subscription used for this + * operation is either invalid or has become inactive. The active subscriptions can be queried + * with {@link SubscriptionManager#getActiveSubscriptionInfoList()}. + * @hide + */ + public static final int CODE_ERROR_INVALID_SUBSCRIPTION = 3; + /**@hide*/ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "CODE_ERROR_", value = { CODE_ERROR_UNSPECIFIED, CODE_ERROR_SERVICE_UNAVAILABLE, - CODE_ERROR_UNSUPPORTED_OPERATION + CODE_ERROR_UNSUPPORTED_OPERATION, + CODE_ERROR_INVALID_SUBSCRIPTION }) public @interface ImsErrorCode {} diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index be5872387d7b..a1a7fcc5dd51 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -31,6 +31,7 @@ import android.net.Uri; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.telephony.AccessNetworkConstants; import android.telephony.SubscriptionManager; import android.telephony.ims.aidl.IImsCapabilityCallback; @@ -375,6 +376,13 @@ public class ImsMmTelManager { c.setExecutor(executor); try { getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder()); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException | IllegalStateException e) { throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); } @@ -390,8 +398,6 @@ public class ImsMmTelManager { * @param c The {@link RegistrationCallback} to be removed. * @see SubscriptionManager.OnSubscriptionsChangedListener * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) - * @throws IllegalArgumentException if the subscription ID associated with this callback is - * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) { @@ -445,6 +451,13 @@ public class ImsMmTelManager { c.setExecutor(executor); try { getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder()); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } catch (IllegalStateException e) { @@ -460,8 +473,6 @@ public class ImsMmTelManager { * inactive subscription, it will result in a no-op. * @param c The MmTel {@link CapabilityCallback} to be removed. * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) - * @throws IllegalArgumentException if the subscription ID associated with this callback is - * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) { @@ -482,12 +493,9 @@ public class ImsMmTelManager { * be enabled as long as the carrier has provisioned these services for the specified * subscription. Other IMS services (SMS/UT) are not affected by this user setting and depend on * carrier requirements. - * - * Modifying this value may also trigger an IMS registration or deregistration, depending on - * whether or not the new value is enabled or disabled. - * + * <p> * Note: If the carrier configuration for advanced calling is not editable or hidden, this - * method will do nothing and will instead always use the default value. + * method will always return the default value. * * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL * @see android.telephony.CarrierConfigManager#KEY_EDITABLE_ENHANCED_4G_LTE_BOOL @@ -495,12 +503,21 @@ public class ImsMmTelManager { * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL * @see #setAdvancedCallingSettingEnabled(boolean) + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for advanced calling is enabled, false otherwise. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled() { try { return getITelephony().isAdvancedCallingSettingEnabled(mSubId); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -526,12 +543,20 @@ public class ImsMmTelManager { * @see android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_AVAILABLE_BOOL * @see #isAdvancedCallingSettingEnabled() + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean isEnabled) { try { getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -597,6 +622,9 @@ public class ImsMmTelManager { /** * The user's setting for whether or not they have enabled the "Video Calling" setting. + * + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user’s “Video Calling†setting is currently enabled. * @see #setVtSettingEnabled(boolean) */ @@ -604,6 +632,13 @@ public class ImsMmTelManager { public boolean isVtSettingEnabled() { try { return getITelephony().isVtSettingEnabled(mSubId); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -611,13 +646,22 @@ public class ImsMmTelManager { /** * Change the user's setting for Video Telephony and enable the Video Telephony capability. + * + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see #isVtSettingEnabled() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean isEnabled) { try { getITelephony().setVtSettingEnabled(mSubId, isEnabled); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -625,12 +669,22 @@ public class ImsMmTelManager { /** * @return true if the user's setting for Voice over WiFi is enabled and false if it is not. + * + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see #setVoWiFiSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled() { try { return getITelephony().isVoWiFiSettingEnabled(mSubId); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -638,6 +692,9 @@ public class ImsMmTelManager { /** * Sets the user's setting for whether or not Voice over WiFi is enabled. + * + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @param isEnabled true if the user's setting for Voice over WiFi is enabled, false otherwise= * @see #isVoWiFiSettingEnabled() */ @@ -645,13 +702,23 @@ public class ImsMmTelManager { public void setVoWiFiSettingEnabled(boolean isEnabled) { try { getITelephony().setVoWiFiSettingEnabled(mSubId, isEnabled); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** + * Returns the user's voice over WiFi roaming setting associated with the current subscription. + * + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @return true if the user's setting for Voice over WiFi while roaming is enabled, false * if disabled. * @see #setVoWiFiRoamingSettingEnabled(boolean) @@ -660,6 +727,13 @@ public class ImsMmTelManager { public boolean isVoWiFiRoamingSettingEnabled() { try { return getITelephony().isVoWiFiRoamingSettingEnabled(mSubId); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -667,15 +741,24 @@ public class ImsMmTelManager { /** * Change the user's setting for Voice over WiFi while roaming. + * * @param isEnabled true if the user's setting for Voice over WiFi while roaming is enabled, * false otherwise. + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see #isVoWiFiRoamingSettingEnabled() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) { try { getITelephony().setVoWiFiRoamingSettingEnabled(mSubId, isEnabled); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -691,19 +774,31 @@ public class ImsMmTelManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see #setVoWiFiSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean isCapable, int mode) { try { getITelephony().setVoWiFiNonPersistent(mSubId, isCapable, mode); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** + * Returns the user's voice over WiFi Roaming mode setting associated with the device. + * + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @return The Voice over WiFi Mode preference set by the user, which can be one of the * following: * - {@link #WIFI_MODE_WIFI_ONLY} @@ -715,6 +810,13 @@ public class ImsMmTelManager { public @WiFiCallingMode int getVoWiFiModeSetting() { try { return getITelephony().getVoWiFiModeSetting(mSubId); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -727,13 +829,21 @@ public class ImsMmTelManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see #getVoWiFiModeSetting() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(@WiFiCallingMode int mode) { try { getITelephony().setVoWiFiModeSetting(mSubId, mode); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -748,12 +858,21 @@ public class ImsMmTelManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see #setVoWiFiRoamingSettingEnabled(boolean) */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @WiFiCallingMode int getVoWiFiRoamingModeSetting() { try { return getITelephony().getVoWiFiRoamingModeSetting(mSubId); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -768,13 +887,21 @@ public class ImsMmTelManager { * - {@link #WIFI_MODE_WIFI_ONLY} * - {@link #WIFI_MODE_CELLULAR_PREFERRED} * - {@link #WIFI_MODE_WIFI_PREFERRED} + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see #getVoWiFiRoamingModeSetting() */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) { try { getITelephony().setVoWiFiRoamingModeSetting(mSubId, mode); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -787,13 +914,21 @@ public class ImsMmTelManager { * {@link android.provider.Settings.Secure#RTT_CALLING_MODE}, which is the global user setting * for RTT. That value is enabled/disabled separately by the user through the Accessibility * settings. + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @param isEnabled if true RTT should be enabled during calls made on this subscription. */ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean isEnabled) { try { getITelephony().setRttCapabilitySetting(mSubId, isEnabled); - return; + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -801,6 +936,9 @@ public class ImsMmTelManager { /** * @return true if TTY over VoLTE is supported + * + * @throws IllegalArgumentException if the subscription associated with this operation is not + * active (SIM is not inserted, ESIM inactive) or invalid. * @see android.telecom.TelecomManager#getCurrentTtyMode * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL */ @@ -808,6 +946,13 @@ public class ImsMmTelManager { boolean isTtyOverVolteEnabled() { try { return getITelephony().isTtyOverVolteEnabled(mSubId); + } catch (ServiceSpecificException e) { + if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) { + // Rethrow as runtime error to keep API compatible. + throw new IllegalArgumentException(e.getMessage()); + } else { + throw new RuntimeException(e.getMessage()); + } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } diff --git a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl index 4433c1c03c1f..53e459697958 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl @@ -17,6 +17,8 @@ package android.telephony.ims.aidl; +import android.os.PersistableBundle; + import android.telephony.ims.aidl.IImsConfigCallback; import com.android.ims.ImsConfigListener; @@ -37,4 +39,5 @@ interface IImsConfig { int setConfigInt(int item, int value); // Return result code defined in ImsConfig#OperationStatusConstants int setConfigString(int item, String value); + void updateImsCarrierConfigs(in PersistableBundle bundle); } diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index 321bfff40652..91b0a43844c9 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -19,6 +19,7 @@ package android.telephony.ims.stub; import android.annotation.IntDef; import android.annotation.SystemApi; import android.content.Context; +import android.os.PersistableBundle; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.telephony.ims.aidl.IImsConfig; @@ -182,6 +183,11 @@ public class ImsConfigImplBase { return retVal; } + @Override + public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException { + getImsConfigImpl().updateImsCarrierConfigs(bundle); + } + private ImsConfigImplBase getImsConfigImpl() throws RemoteException { ImsConfigImplBase ref = mImsConfigImplBaseWeakReference.get(); if (ref == null) { @@ -387,4 +393,11 @@ public class ImsConfigImplBase { // Base Implementation - To be overridden. return null; } + + /** + * @hide + */ + public void updateImsCarrierConfigs(PersistableBundle bundle) { + // Base Implementation - Should be overridden + } } diff --git a/test-base/Android.mk b/test-base/Android.mk deleted file mode 100644 index a9d30cf3131a..000000000000 --- a/test-base/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (C) 2016 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. -# - -LOCAL_PATH:= $(call my-dir) - -ifeq ($(HOST_OS),linux) -# Build the legacy-performance-test-hostdex library -# ================================================= -# This contains the android.test.PerformanceTestCase class only -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := src/android/test/PerformanceTestCase.java -LOCAL_MODULE := legacy-performance-test-hostdex - -include $(BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY) -endif # HOST_OS == linux diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 11150dd8e882..b725920ba014 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -386,6 +386,9 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, manifest_action["package-verifier"]; manifest_action["meta-data"] = meta_data_action; manifest_action["uses-split"].Action(RequiredNameIsJavaPackage); + manifest_action["queries"]["package"].Action(RequiredNameIsJavaPackage); + manifest_action["queries"]["intent"] = intent_filter_action; + // TODO: more complicated component name tag manifest_action["key-sets"]["key-set"]["public-key"]; manifest_action["key-sets"]["upgrade-key-set"]; diff --git a/tools/aapt2/optimize/ResourcePathShortener.cpp b/tools/aapt2/optimize/ResourcePathShortener.cpp index 6b11de759d2d..7f5d10475f93 100644 --- a/tools/aapt2/optimize/ResourcePathShortener.cpp +++ b/tools/aapt2/optimize/ResourcePathShortener.cpp @@ -16,7 +16,6 @@ #include "optimize/ResourcePathShortener.h" -#include <math.h> #include <unordered_set> #include "androidfw/StringPiece.h" @@ -51,18 +50,15 @@ std::string ShortenFileName(const android::StringPiece& file_path, int output_le } -// Calculate the optimal hash length such that an average of 10% of resources -// collide in their shortened path. +// Return the optimal hash length such that at most 10% of resources collide in +// their shortened path. // Reference: http://matt.might.net/articles/counting-hash-collisions/ int OptimalShortenedLength(int num_resources) { - int num_chars = 2; - double N = 64*64; // hash space when hash is 2 chars long - double max_collisions = num_resources * 0.1; - while (num_resources - N + N * pow((N - 1) / N, num_resources) > max_collisions) { - N *= 64; - num_chars++; + if (num_resources > 4000) { + return 3; + } else { + return 2; } - return num_chars; } std::string GetShortenedPath(const android::StringPiece& shortened_filename, diff --git a/tools/preload2/Android.bp b/tools/preload2/Android.bp deleted file mode 100644 index 5809421da3e8..000000000000 --- a/tools/preload2/Android.bp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (C) 2015 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library_host { - name: "preload2", - - srcs: ["src/**/*.java"], - - // To connect to devices (and take hprof dumps). - static_libs: [ - "ddmlib-prebuilt", - "tools-common-prebuilt", - - // To process hprof dumps. - "perflib-prebuilt", - - "trove-prebuilt", - "guavalib", - - // For JDWP access we use the framework in the JDWP tests from Apache Harmony, for - // convenience (and to not depend on internal JDK APIs). - "apache-harmony-jdwp-tests", - "junit", - ], - - // Copy to build artifacts - dist: { - targets: [ - "dist_files", - ], - }, -} - -// Copy the preload-tool shell script to the host's bin directory. -sh_binary_host { - name: "preload-tool", - src: "preload-tool", - required: ["preload2"], -} diff --git a/tools/preload2/preload-tool b/tools/preload2/preload-tool deleted file mode 100644 index 322b62fda071..000000000000 --- a/tools/preload2/preload-tool +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2015 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script is used on the host only. It uses a common subset -# shell dialect that should work well. It is partially derived -# from art/tools/art. - -function follow_links() { - if [ z"$BASH_SOURCE" != z ]; then - file="$BASH_SOURCE" - else - file="$0" - fi - while [ -h "$file" ]; do - # On Mac OS, readlink -f doesn't work. - file="$(readlink "$file")" - done - echo "$file" -} - - -PROG_NAME="$(follow_links)" -PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" -ANDROID_ROOT=$PROG_DIR/.. - -java -cp $ANDROID_ROOT/framework/preload2.jar com.android.preload.Main $@ diff --git a/tools/preload2/src/com/android/preload/ClientUtils.java b/tools/preload2/src/com/android/preload/ClientUtils.java deleted file mode 100644 index 71ef025d6587..000000000000 --- a/tools/preload2/src/com/android/preload/ClientUtils.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener; -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; - -/** - * Helper class for common communication with a Client (the ddms name for a running application). - * - * Instances take a default timeout parameter that's applied to all functions without explicit - * timeout. Timeouts are in milliseconds. - */ -public class ClientUtils { - - private int defaultTimeout; - - public ClientUtils() { - this(10000); - } - - public ClientUtils(int defaultTimeout) { - this.defaultTimeout = defaultTimeout; - } - - /** - * Shortcut for findClient with default timeout. - */ - public Client findClient(IDevice device, String processName, int processPid) { - return findClient(device, processName, processPid, defaultTimeout); - } - - /** - * Find the client with the given process name or process id. The name takes precedence over - * the process id (if valid). Stop looking after the given timeout. - * - * @param device The device to communicate with. - * @param processName The name of the process. May be null. - * @param processPid The pid of the process. Values less than or equal to zero are ignored. - * @param timeout The amount of milliseconds to wait, at most. - * @return The client, if found. Otherwise null. - */ - public Client findClient(IDevice device, String processName, int processPid, int timeout) { - WaitForClient wfc = new WaitForClient(device, processName, processPid, timeout); - return wfc.get(); - } - - /** - * Shortcut for findAllClients with default timeout. - */ - public Client[] findAllClients(IDevice device) { - return findAllClients(device, defaultTimeout); - } - - /** - * Retrieve all clients known to the given device. Wait at most the given timeout. - * - * @param device The device to investigate. - * @param timeout The amount of milliseconds to wait, at most. - * @return An array of clients running on the given device. May be null depending on the - * device implementation. - */ - public Client[] findAllClients(IDevice device, int timeout) { - if (device.hasClients()) { - return device.getClients(); - } - WaitForClients wfc = new WaitForClients(device, timeout); - return wfc.get(); - } - - private static class WaitForClient implements IClientChangeListener { - - private IDevice device; - private String processName; - private int processPid; - private long timeout; - private Client result; - - public WaitForClient(IDevice device, String processName, int processPid, long timeout) { - this.device = device; - this.processName = processName; - this.processPid = processPid; - this.timeout = timeout; - this.result = null; - } - - public Client get() { - synchronized (this) { - AndroidDebugBridge.addClientChangeListener(this); - - // Maybe it's already there. - if (result == null) { - result = searchForClient(device); - } - - if (result == null) { - try { - wait(timeout); - } catch (InterruptedException e) { - // Note: doesn't guard for spurious wakeup. - } - } - } - - AndroidDebugBridge.removeClientChangeListener(this); - return result; - } - - private Client searchForClient(IDevice device) { - if (processName != null) { - Client tmp = device.getClient(processName); - if (tmp != null) { - return tmp; - } - } - if (processPid > 0) { - String name = device.getClientName(processPid); - if (name != null && !name.isEmpty()) { - Client tmp = device.getClient(name); - if (tmp != null) { - return tmp; - } - } - } - if (processPid > 0) { - // Try manual search. - for (Client cl : device.getClients()) { - if (cl.getClientData().getPid() == processPid - && cl.getClientData().getClientDescription() != null) { - return cl; - } - } - } - return null; - } - - private boolean isTargetClient(Client c) { - if (processPid > 0 && c.getClientData().getPid() == processPid) { - return true; - } - if (processName != null - && processName.equals(c.getClientData().getClientDescription())) { - return true; - } - return false; - } - - @Override - public void clientChanged(Client arg0, int arg1) { - synchronized (this) { - if ((arg1 & Client.CHANGE_INFO) != 0 && (arg0.getDevice() == device)) { - if (isTargetClient(arg0)) { - result = arg0; - notifyAll(); - } - } - } - } - } - - private static class WaitForClients implements IClientChangeListener { - - private IDevice device; - private long timeout; - - public WaitForClients(IDevice device, long timeout) { - this.device = device; - this.timeout = timeout; - } - - public Client[] get() { - synchronized (this) { - AndroidDebugBridge.addClientChangeListener(this); - - if (device.hasClients()) { - return device.getClients(); - } - - try { - wait(timeout); // Note: doesn't guard for spurious wakeup. - } catch (InterruptedException exc) { - } - - // We will be woken up when the first client data arrives. Sleep a little longer - // to give (hopefully all of) the rest of the clients a chance to become available. - // Note: a loop with timeout is brittle as well and complicated, just accept this - // for now. - try { - Thread.sleep(500); - } catch (InterruptedException exc) { - } - } - - AndroidDebugBridge.removeClientChangeListener(this); - - return device.getClients(); - } - - @Override - public void clientChanged(Client arg0, int arg1) { - synchronized (this) { - if ((arg1 & Client.CHANGE_INFO) != 0 && (arg0.getDevice() == device)) { - notifyAll(); - } - } - } - } -} diff --git a/tools/preload2/src/com/android/preload/DeviceUtils.java b/tools/preload2/src/com/android/preload/DeviceUtils.java deleted file mode 100644 index 18cab7bee12d..000000000000 --- a/tools/preload2/src/com/android/preload/DeviceUtils.java +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload; - -import com.android.ddmlib.AdbCommandRejectedException; -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; -import com.android.preload.classdataretrieval.hprof.Hprof; -import com.android.ddmlib.DdmPreferences; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.IShellOutputReceiver; -import com.android.ddmlib.SyncException; -import com.android.ddmlib.TimeoutException; - -import java.io.File; -import java.io.IOException; -import java.util.Date; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -/** - * Helper class for some device routines. - */ -public class DeviceUtils { - - // Locations - private static final String PRELOADED_CLASSES_FILE = "/etc/preloaded-classes"; - // Shell commands - private static final String CREATE_EMPTY_PRELOADED_CMD = "touch " + PRELOADED_CLASSES_FILE; - private static final String DELETE_CACHE_CMD = "rm /data/dalvik-cache/*/*boot.art"; - private static final String DELETE_PRELOADED_CMD = "rm " + PRELOADED_CLASSES_FILE; - private static final String READ_PRELOADED_CMD = "cat " + PRELOADED_CLASSES_FILE; - private static final String START_SHELL_CMD = "start"; - private static final String STOP_SHELL_CMD = "stop"; - private static final String REMOUNT_SYSTEM_CMD = "mount -o rw,remount /system"; - private static final String UNSET_BOOTCOMPLETE_CMD = "setprop dev.bootcomplete \"0\""; - - public static void init(int debugPort) { - DdmPreferences.setSelectedDebugPort(debugPort); - - Hprof.init(); - - AndroidDebugBridge.init(true); - - AndroidDebugBridge.createBridge(); - } - - /** - * Run a command in the shell on the device. - */ - public static void doShell(IDevice device, String cmdline, long timeout, TimeUnit unit) { - doShell(device, cmdline, new NullShellOutputReceiver(), timeout, unit); - } - - /** - * Run a command in the shell on the device. Collects and returns the console output. - */ - public static String doShellReturnString(IDevice device, String cmdline, long timeout, - TimeUnit unit) { - CollectStringShellOutputReceiver rec = new CollectStringShellOutputReceiver(); - doShell(device, cmdline, rec, timeout, unit); - return rec.toString(); - } - - /** - * Run a command in the shell on the device, directing all output to the given receiver. - */ - public static void doShell(IDevice device, String cmdline, IShellOutputReceiver receiver, - long timeout, TimeUnit unit) { - try { - device.executeShellCommand(cmdline, receiver, timeout, unit); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Run am start on the device. - */ - public static void doAMStart(IDevice device, String name, String activity) { - doShell(device, "am start -n " + name + " /." + activity, 30, TimeUnit.SECONDS); - } - - /** - * Find the device with the given serial. Give up after the given timeout (in milliseconds). - */ - public static IDevice findDevice(String serial, int timeout) { - WaitForDevice wfd = new WaitForDevice(serial, timeout); - return wfd.get(); - } - - /** - * Get all devices ddms knows about. Wait at most for the given timeout. - */ - public static IDevice[] findDevices(int timeout) { - WaitForDevice wfd = new WaitForDevice(null, timeout); - wfd.get(); - return AndroidDebugBridge.getBridge().getDevices(); - } - - /** - * Return the build type of the given device. This is the value of the "ro.build.type" - * system property. - */ - public static String getBuildType(IDevice device) { - try { - Future<String> buildType = device.getSystemProperty("ro.build.type"); - return buildType.get(500, TimeUnit.MILLISECONDS); - } catch (Exception e) { - } - return null; - } - - /** - * Check whether the given device has a pre-optimized boot image. More precisely, checks - * whether /system/framework/ * /boot.art exists. - */ - public static boolean hasPrebuiltBootImage(IDevice device) { - String ret = - doShellReturnString(device, "ls /system/framework/*/boot.art", 500, TimeUnit.MILLISECONDS); - - return !ret.contains("No such file or directory"); - } - - /** - * Write over the preloaded-classes file with an empty or existing file and regenerate the boot - * image as necessary. - * - * @param device - * @param pcFile - * @param bootTimeout - * @throws AdbCommandRejectedException - * @throws IOException - * @throws TimeoutException - * @throws SyncException - * @return true if successfully overwritten, false otherwise - */ - public static boolean overwritePreloaded(IDevice device, File pcFile, long bootTimeout) - throws AdbCommandRejectedException, IOException, TimeoutException, SyncException { - boolean writeEmpty = (pcFile == null); - if (writeEmpty) { - // Check if the preloaded-classes file is already empty. - String oldContent = - doShellReturnString(device, READ_PRELOADED_CMD, 1, TimeUnit.SECONDS); - if (oldContent.trim().equals("")) { - System.out.println("Preloaded-classes already empty."); - return true; - } - } - - // Stop the system server etc. - doShell(device, STOP_SHELL_CMD, 1, TimeUnit.SECONDS); - // Remount the read-only system partition - doShell(device, REMOUNT_SYSTEM_CMD, 1, TimeUnit.SECONDS); - // Delete the preloaded-classes file - doShell(device, DELETE_PRELOADED_CMD, 1, TimeUnit.SECONDS); - // Delete the dalvik cache files - doShell(device, DELETE_CACHE_CMD, 1, TimeUnit.SECONDS); - if (writeEmpty) { - // Write an empty preloaded-classes file - doShell(device, CREATE_EMPTY_PRELOADED_CMD, 500, TimeUnit.MILLISECONDS); - } else { - // Push the new preloaded-classes file - device.pushFile(pcFile.getAbsolutePath(), PRELOADED_CLASSES_FILE); - } - // Manually reset the boot complete flag - doShell(device, UNSET_BOOTCOMPLETE_CMD, 1, TimeUnit.SECONDS); - // Restart system server on the device - doShell(device, START_SHELL_CMD, 1, TimeUnit.SECONDS); - // Wait for the boot complete flag and return the outcome. - return waitForBootComplete(device, bootTimeout); - } - - private static boolean waitForBootComplete(IDevice device, long timeout) { - // Do a loop checking each second whether bootcomplete. Wait for at most the given - // threshold. - Date startDate = new Date(); - for (;;) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // Ignore spurious wakeup. - } - // Check whether bootcomplete. - String ret = - doShellReturnString(device, "getprop dev.bootcomplete", 500, TimeUnit.MILLISECONDS); - if (ret.trim().equals("1")) { - break; - } - System.out.println("Still not booted: " + ret); - - // Check whether we timed out. This is a simplistic check that doesn't take into account - // things like switches in time. - Date endDate = new Date(); - long seconds = - TimeUnit.SECONDS.convert(endDate.getTime() - startDate.getTime(), TimeUnit.MILLISECONDS); - if (seconds > timeout) { - return false; - } - } - - return true; - } - - /** - * Enable method-tracing on device. The system should be restarted after this. - */ - public static void enableTracing(IDevice device) { - // Disable selinux. - doShell(device, "setenforce 0", 100, TimeUnit.MILLISECONDS); - - // Make the profile directory world-writable. - doShell(device, "chmod 777 /data/dalvik-cache/profiles", 100, TimeUnit.MILLISECONDS); - - // Enable streaming method tracing with a small 1K buffer. - doShell(device, "setprop dalvik.vm.method-trace true", 100, TimeUnit.MILLISECONDS); - doShell(device, "setprop dalvik.vm.method-trace-file " - + "/data/dalvik-cache/profiles/zygote.trace.bin", 100, TimeUnit.MILLISECONDS); - doShell(device, "setprop dalvik.vm.method-trace-file-siz 1024", 100, TimeUnit.MILLISECONDS); - doShell(device, "setprop dalvik.vm.method-trace-stream true", 100, TimeUnit.MILLISECONDS); - } - - private static class NullShellOutputReceiver implements IShellOutputReceiver { - @Override - public boolean isCancelled() { - return false; - } - - @Override - public void flush() {} - - @Override - public void addOutput(byte[] arg0, int arg1, int arg2) {} - } - - private static class CollectStringShellOutputReceiver implements IShellOutputReceiver { - - private StringBuilder builder = new StringBuilder(); - - @Override - public String toString() { - String ret = builder.toString(); - // Strip trailing newlines. They are especially ugly because adb uses DOS line endings. - while (ret.endsWith("\r") || ret.endsWith("\n")) { - ret = ret.substring(0, ret.length() - 1); - } - return ret; - } - - @Override - public void addOutput(byte[] arg0, int arg1, int arg2) { - builder.append(new String(arg0, arg1, arg2)); - } - - @Override - public void flush() {} - - @Override - public boolean isCancelled() { - return false; - } - } - - private static class WaitForDevice { - - private String serial; - private long timeout; - private IDevice device; - - public WaitForDevice(String serial, long timeout) { - this.serial = serial; - this.timeout = timeout; - device = null; - } - - public IDevice get() { - if (device == null) { - WaitForDeviceListener wfdl = new WaitForDeviceListener(serial); - synchronized (wfdl) { - AndroidDebugBridge.addDeviceChangeListener(wfdl); - - // Check whether we already know about this device. - IDevice[] devices = AndroidDebugBridge.getBridge().getDevices(); - if (serial != null) { - for (IDevice d : devices) { - if (serial.equals(d.getSerialNumber())) { - // Only accept if there are clients already. Else wait for the callback informing - // us that we now have clients. - if (d.hasClients()) { - device = d; - } - - break; - } - } - } else { - if (devices.length > 0) { - device = devices[0]; - } - } - - if (device == null) { - try { - wfdl.wait(timeout); - } catch (InterruptedException e) { - // Ignore spurious wakeups. - } - device = wfdl.getDevice(); - } - - AndroidDebugBridge.removeDeviceChangeListener(wfdl); - } - } - - if (device != null) { - // Wait for clients. - WaitForClientsListener wfcl = new WaitForClientsListener(device); - synchronized (wfcl) { - AndroidDebugBridge.addDeviceChangeListener(wfcl); - - if (!device.hasClients()) { - try { - wfcl.wait(timeout); - } catch (InterruptedException e) { - // Ignore spurious wakeups. - } - } - - AndroidDebugBridge.removeDeviceChangeListener(wfcl); - } - } - - return device; - } - - private static class WaitForDeviceListener implements IDeviceChangeListener { - - private String serial; - private IDevice device; - - public WaitForDeviceListener(String serial) { - this.serial = serial; - } - - public IDevice getDevice() { - return device; - } - - @Override - public void deviceChanged(IDevice arg0, int arg1) { - // We may get a device changed instead of connected. Handle like a connection. - deviceConnected(arg0); - } - - @Override - public void deviceConnected(IDevice arg0) { - if (device != null) { - // Ignore updates. - return; - } - - if (serial == null || serial.equals(arg0.getSerialNumber())) { - device = arg0; - synchronized (this) { - notifyAll(); - } - } - } - - @Override - public void deviceDisconnected(IDevice arg0) { - // Ignore disconnects. - } - - } - - private static class WaitForClientsListener implements IDeviceChangeListener { - - private IDevice myDevice; - - public WaitForClientsListener(IDevice myDevice) { - this.myDevice = myDevice; - } - - @Override - public void deviceChanged(IDevice arg0, int arg1) { - if (arg0 == myDevice && (arg1 & IDevice.CHANGE_CLIENT_LIST) != 0) { - // Got a client list, done here. - synchronized (this) { - notifyAll(); - } - } - } - - @Override - public void deviceConnected(IDevice arg0) { - } - - @Override - public void deviceDisconnected(IDevice arg0) { - } - - } - } - -} diff --git a/tools/preload2/src/com/android/preload/DumpData.java b/tools/preload2/src/com/android/preload/DumpData.java deleted file mode 100644 index d99722416a1d..000000000000 --- a/tools/preload2/src/com/android/preload/DumpData.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload; - -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Holds the collected data for a process. - */ -public class DumpData { - /** - * Name of the package (=application). - */ - String packageName; - - /** - * A map of class name to a string for the classloader. This may be a toString equivalent, - * or just a unique ID. - */ - Map<String, String> dumpData; - - /** - * The Date when this data was captured. Mostly for display purposes. - */ - Date date; - - /** - * A cached value for the number of boot classpath classes (classloader value in dumpData is - * null). - */ - int bcpClasses; - - public DumpData(String packageName, Map<String, String> dumpData, Date date) { - this.packageName = packageName; - this.dumpData = dumpData; - this.date = date; - - countBootClassPath(); - } - - public String getPackageName() { - return packageName; - } - - public Date getDate() { - return date; - } - - public Map<String, String> getDumpData() { - return dumpData; - } - - public void countBootClassPath() { - bcpClasses = 0; - for (Map.Entry<String, String> e : dumpData.entrySet()) { - if (e.getValue() == null) { - bcpClasses++; - } - } - } - - // Return an inverted mapping. - public Map<String, Set<String>> invertData() { - Map<String, Set<String>> ret = new HashMap<>(); - for (Map.Entry<String, String> e : dumpData.entrySet()) { - if (!ret.containsKey(e.getValue())) { - ret.put(e.getValue(), new HashSet<String>()); - } - ret.get(e.getValue()).add(e.getKey()); - } - return ret; - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/DumpDataIO.java b/tools/preload2/src/com/android/preload/DumpDataIO.java deleted file mode 100644 index 28625c5531e4..000000000000 --- a/tools/preload2/src/com/android/preload/DumpDataIO.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload; - -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -import java.io.File; -import java.io.FileReader; -import java.text.DateFormat; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -/** - * Helper class for serialization and deserialization of a collection of DumpData objects to XML. - */ -public class DumpDataIO { - - /** - * Serialize the given collection to an XML document. Returns the produced string. - */ - public static String serialize(Collection<DumpData> data) { - // We'll do this by hand, constructing a DOM or similar is too complicated for our simple - // use case. - - StringBuilder sb = new StringBuilder(); - sb.append("<preloaded-classes-data>\n"); - - for (DumpData d : data) { - serialize(d, sb); - } - - sb.append("</preloaded-classes-data>\n"); - return sb.toString(); - } - - private static void serialize(DumpData d, StringBuilder sb) { - sb.append("<data package=\"" + d.packageName + "\" date=\"" + - DateFormat.getDateTimeInstance().format(d.date) +"\">\n"); - - for (Map.Entry<String, String> e : d.dumpData.entrySet()) { - sb.append("<class name=\"" + e.getKey() + "\" classloader=\"" + e.getValue() + "\"/>\n"); - } - - sb.append("</data>\n"); - } - - /** - * Load a collection of DumpData objects from the given file. - */ - public static Collection<DumpData> deserialize(File f) throws Exception { - // Use SAX parsing. Our format is very simple. Don't do any schema validation or such. - - SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setNamespaceAware(false); - SAXParser saxParser = spf.newSAXParser(); - - XMLReader xmlReader = saxParser.getXMLReader(); - DumpDataContentHandler ddch = new DumpDataContentHandler(); - xmlReader.setContentHandler(ddch); - xmlReader.parse(new InputSource(new FileReader(f))); - - return ddch.data; - } - - private static class DumpDataContentHandler extends DefaultHandler { - Collection<DumpData> data = new LinkedList<DumpData>(); - DumpData openData = null; - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - if (qName.equals("data")) { - if (openData != null) { - throw new IllegalStateException(); - } - String pkg = attributes.getValue("package"); - String dateString = attributes.getValue("date"); - - if (pkg == null || dateString == null) { - throw new IllegalArgumentException(); - } - - try { - Date date = DateFormat.getDateTimeInstance().parse(dateString); - openData = new DumpData(pkg, new HashMap<String, String>(), date); - } catch (Exception e) { - throw new RuntimeException(e); - } - } else if (qName.equals("class")) { - if (openData == null) { - throw new IllegalStateException(); - } - String className = attributes.getValue("name"); - String classLoader = attributes.getValue("classloader"); - - if (className == null || classLoader == null) { - throw new IllegalArgumentException(); - } - - openData.dumpData.put(className, classLoader.equals("null") ? null : classLoader); - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - if (qName.equals("data")) { - if (openData == null) { - throw new IllegalStateException(); - } - openData.countBootClassPath(); - - data.add(openData); - openData = null; - } - } - } -} diff --git a/tools/preload2/src/com/android/preload/DumpTableModel.java b/tools/preload2/src/com/android/preload/DumpTableModel.java deleted file mode 100644 index d97cbf0df5e5..000000000000 --- a/tools/preload2/src/com/android/preload/DumpTableModel.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload; - -import java.util.ArrayList; -import java.util.List; - -import javax.swing.table.AbstractTableModel; - -/** - * A table model for collected DumpData. This is both the internal storage as well as the model - * for display. - */ -public class DumpTableModel extends AbstractTableModel { - - private List<DumpData> data = new ArrayList<DumpData>(); - - public void addData(DumpData d) { - data.add(d); - fireTableRowsInserted(data.size() - 1, data.size() - 1); - } - - public void clear() { - int size = data.size(); - if (size > 0) { - data.clear(); - fireTableRowsDeleted(0, size - 1); - } - } - - public List<DumpData> getData() { - return data; - } - - @Override - public int getRowCount() { - return data.size(); - } - - @Override - public int getColumnCount() { - return 4; - } - - @Override - public String getColumnName(int column) { - switch (column) { - case 0: - return "Package"; - case 1: - return "Date"; - case 2: - return "# All Classes"; - case 3: - return "# Boot Classpath Classes"; - - default: - throw new IndexOutOfBoundsException(String.valueOf(column)); - } - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - DumpData d = data.get(rowIndex); - switch (columnIndex) { - case 0: - return d.packageName; - case 1: - return d.date; - case 2: - return d.dumpData.size(); - case 3: - return d.bcpClasses; - - default: - throw new IndexOutOfBoundsException(String.valueOf(columnIndex)); - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/Main.java b/tools/preload2/src/com/android/preload/Main.java deleted file mode 100644 index 2265e9557c4b..000000000000 --- a/tools/preload2/src/com/android/preload/Main.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload; - -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.preload.actions.ClearTableAction; -import com.android.preload.actions.ComputeThresholdAction; -import com.android.preload.actions.ComputeThresholdXAction; -import com.android.preload.actions.DeviceSpecific; -import com.android.preload.actions.ExportAction; -import com.android.preload.actions.ImportAction; -import com.android.preload.actions.ReloadListAction; -import com.android.preload.actions.RunMonkeyAction; -import com.android.preload.actions.ScanAllPackagesAction; -import com.android.preload.actions.ScanPackageAction; -import com.android.preload.actions.ShowDataAction; -import com.android.preload.actions.WritePreloadedClassesAction; -import com.android.preload.classdataretrieval.ClassDataRetriever; -import com.android.preload.classdataretrieval.hprof.Hprof; -import com.android.preload.classdataretrieval.jdwp.JDWPClassDataRetriever; -import com.android.preload.ui.IUI; -import com.android.preload.ui.SequenceUI; -import com.android.preload.ui.SwingUI; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; - -import javax.swing.Action; -import javax.swing.DefaultListModel; - -public class Main { - - /** - * Enable tracing mode. This is a work-in-progress to derive compiled-methods data, so it is - * off for now. - */ - public final static boolean ENABLE_TRACING = false; - - /** - * Ten-second timeout. - */ - public final static int DEFAULT_TIMEOUT_MILLIS = 10 * 1000; - - /** - * Hprof timeout. Two minutes. - */ - public final static int HPROF_TIMEOUT_MILLIS = 120 * 1000; - - private IDevice device; - private static ClientUtils clientUtils; - - private DumpTableModel dataTableModel; - private DefaultListModel<Client> clientListModel; - - private IUI ui; - - // Actions that need to be updated once a device is selected. - private Collection<DeviceSpecific> deviceSpecificActions; - - // Current main instance. - private static Main top; - private static boolean useJdwpClassDataRetriever = false; - - public final static String CLASS_PRELOAD_BLACKLIST = "android.app.AlarmManager$" + "|" - + "android.app.SearchManager$" + "|" + "android.os.FileObserver$" + "|" - + "com.android.server.PackageManagerService\\$AppDirObserver$" + "|" + - - - // Threads - "android.os.AsyncTask$" + "|" + "android.pim.ContactsAsyncHelper$" + "|" - + "android.webkit.WebViewClassic\\$1$" + "|" + "java.lang.ProcessManager$" + "|" - + "(.*\\$NoPreloadHolder$)"; - - public final static String SCAN_ALL_CMD = "scan-all"; - public final static String SCAN_PACKAGE_CMD = "scan"; - public final static String COMPUTE_FILE_CMD = "comp"; - public final static String EXPORT_CMD = "export"; - public final static String IMPORT_CMD = "import"; - public final static String WRITE_CMD = "write"; - - /** - * @param args - */ - public static void main(String[] args) { - Main m; - if (args.length > 0 && args[0].equals("--seq")) { - m = createSequencedMain(args); - } else { - m = new Main(new SwingUI()); - } - - top = m; - m.startUp(); - } - - public Main(IUI ui) { - this.ui = ui; - - clientListModel = new DefaultListModel<Client>(); - dataTableModel = new DumpTableModel(); - - clientUtils = new ClientUtils(DEFAULT_TIMEOUT_MILLIS); // Client utils with 10s timeout. - - List<Action> actions = new ArrayList<Action>(); - actions.add(new ReloadListAction(clientUtils, null, clientListModel)); - actions.add(new ClearTableAction(dataTableModel)); - actions.add(new RunMonkeyAction(null, dataTableModel)); - actions.add(new ScanPackageAction(clientUtils, null, dataTableModel)); - actions.add(new ScanAllPackagesAction(clientUtils, null, dataTableModel)); - actions.add(new ComputeThresholdAction("Compute preloaded-classes", dataTableModel, 2, - CLASS_PRELOAD_BLACKLIST)); - actions.add(new ComputeThresholdAction("Compute compiled-classes", dataTableModel, 1, - null)); - actions.add(new ComputeThresholdXAction("Compute(X)", dataTableModel, - CLASS_PRELOAD_BLACKLIST)); - actions.add(new WritePreloadedClassesAction(clientUtils, null, dataTableModel)); - actions.add(new ShowDataAction(dataTableModel)); - actions.add(new ImportAction(dataTableModel)); - actions.add(new ExportAction(dataTableModel)); - - deviceSpecificActions = new ArrayList<DeviceSpecific>(); - for (Action a : actions) { - if (a instanceof DeviceSpecific) { - deviceSpecificActions.add((DeviceSpecific)a); - } - } - - ui.prepare(clientListModel, dataTableModel, actions); - } - - /** - * @param args - * @return - */ - private static Main createSequencedMain(String[] args) { - SequenceUI ui = new SequenceUI(); - Main main = new Main(ui); - - Iterator<String> it = Arrays.asList(args).iterator(); - it.next(); // --seq - // Setup - ui.choice("#" + it.next()); // Device. - ui.confirmNo(); // Prepare: no. - // Actions - try { - while (it.hasNext()) { - String op = it.next(); - // Operation: Scan a single package - if (SCAN_PACKAGE_CMD.equals(op)) { - System.out.println("Scanning package."); - ui.action(ScanPackageAction.class); - ui.client(it.next()); - // Operation: Scan all packages - } else if (SCAN_ALL_CMD.equals(op)) { - System.out.println("Scanning all packages."); - ui.action(ScanAllPackagesAction.class); - // Operation: Export the output to a file - } else if (EXPORT_CMD.equals(op)) { - System.out.println("Exporting data."); - ui.action(ExportAction.class); - ui.output(new File(it.next())); - // Operation: Import the input from a file or directory - } else if (IMPORT_CMD.equals(op)) { - System.out.println("Importing data."); - File file = new File(it.next()); - if (!file.exists()) { - throw new RuntimeException( - String.format("File does not exist, %s.", file.getAbsolutePath())); - } else if (file.isFile()) { - ui.action(ImportAction.class); - ui.input(file); - } else if (file.isDirectory()) { - for (File content : file.listFiles()) { - ui.action(ImportAction.class); - ui.input(content); - } - } - // Operation: Compute preloaded classes with specific threshold - } else if (COMPUTE_FILE_CMD.equals(op)) { - System.out.println("Compute preloaded classes."); - ui.action(ComputeThresholdXAction.class); - ui.input(it.next()); - ui.confirmYes(); - ui.output(new File(it.next())); - // Operation: Write preloaded classes from a specific file - } else if (WRITE_CMD.equals(op)) { - System.out.println("Writing preloaded classes."); - ui.action(WritePreloadedClassesAction.class); - ui.input(new File(it.next())); - } - } - } catch (NoSuchElementException e) { - System.out.println("Failed to parse action sequence correctly."); - throw e; - } - - return main; - } - - public static IUI getUI() { - return top.ui; - } - - public static ClassDataRetriever getClassDataRetriever() { - if (useJdwpClassDataRetriever) { - return new JDWPClassDataRetriever(); - } else { - return new Hprof(HPROF_TIMEOUT_MILLIS); - } - } - - public IDevice getDevice() { - return device; - } - - public void setDevice(IDevice device) { - this.device = device; - for (DeviceSpecific ds : deviceSpecificActions) { - ds.setDevice(device); - } - } - - public DefaultListModel<Client> getClientListModel() { - return clientListModel; - } - - static class DeviceWrapper { - IDevice device; - - public DeviceWrapper(IDevice d) { - device = d; - } - - @Override - public String toString() { - return device.getName() + " (#" + device.getSerialNumber() + ")"; - } - } - - private void startUp() { - getUI().showWaitDialog(); - initDevice(); - - // Load clients. - new ReloadListAction(clientUtils, getDevice(), clientListModel).run(); - - getUI().hideWaitDialog(); - getUI().ready(); - } - - private void initDevice() { - DeviceUtils.init(DEFAULT_TIMEOUT_MILLIS); - - IDevice devices[] = DeviceUtils.findDevices(DEFAULT_TIMEOUT_MILLIS); - if (devices == null || devices.length == 0) { - throw new RuntimeException("Could not find any devices..."); - } - - getUI().hideWaitDialog(); - - DeviceWrapper deviceWrappers[] = new DeviceWrapper[devices.length]; - for (int i = 0; i < devices.length; i++) { - deviceWrappers[i] = new DeviceWrapper(devices[i]); - } - - DeviceWrapper ret = Main.getUI().showChoiceDialog("Choose a device", "Choose device", - deviceWrappers); - if (ret != null) { - setDevice(ret.device); - } else { - System.exit(0); - } - - boolean prepare = Main.getUI().showConfirmDialog("Prepare device?", - "Do you want to prepare the device? This is highly recommended."); - if (prepare) { - String buildType = DeviceUtils.getBuildType(device); - if (buildType == null || (!buildType.equals("userdebug") && !buildType.equals("eng"))) { - Main.getUI().showMessageDialog("Need a userdebug or eng build! (Found " + buildType - + ")"); - return; - } - if (DeviceUtils.hasPrebuiltBootImage(device)) { - Main.getUI().showMessageDialog("Cannot prepare a device with pre-optimized boot " - + "image!"); - return; - } - - if (ENABLE_TRACING) { - DeviceUtils.enableTracing(device); - } - - Main.getUI().showMessageDialog("The device will reboot. This will potentially take a " - + "long time. Please be patient."); - boolean success = false; - try { - success = DeviceUtils.overwritePreloaded(device, null, 15 * 60); - } catch (Exception e) { - System.err.println(e); - } finally { - if (!success) { - Main.getUI().showMessageDialog( - "Removing preloaded-classes failed unexpectedly!"); - } - } - } - } - - public static Map<String, String> findAndGetClassData(IDevice device, String packageName) - throws Exception { - Client client = clientUtils.findClient(device, packageName, -1); - if (client == null) { - throw new RuntimeException("Could not find client..."); - } - System.out.println("Found client: " + client); - - return getClassDataRetriever().getClassData(client); - } - -} diff --git a/tools/preload2/src/com/android/preload/actions/AbstractThreadedAction.java b/tools/preload2/src/com/android/preload/actions/AbstractThreadedAction.java deleted file mode 100644 index 5787d8507230..000000000000 --- a/tools/preload2/src/com/android/preload/actions/AbstractThreadedAction.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.preload.Main; -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; - -public abstract class AbstractThreadedAction extends AbstractAction implements Runnable { - - protected AbstractThreadedAction(String title) { - super(title); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (Main.getUI().isSingleThreaded()) { - run(); - } else { - new Thread(this).start(); - } - } - -} diff --git a/tools/preload2/src/com/android/preload/actions/AbstractThreadedDeviceSpecificAction.java b/tools/preload2/src/com/android/preload/actions/AbstractThreadedDeviceSpecificAction.java deleted file mode 100644 index 7906417b7a8d..000000000000 --- a/tools/preload2/src/com/android/preload/actions/AbstractThreadedDeviceSpecificAction.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.ddmlib.IDevice; - -import java.awt.event.ActionEvent; - -public abstract class AbstractThreadedDeviceSpecificAction extends AbstractThreadedAction - implements DeviceSpecific { - - protected IDevice device; - - protected AbstractThreadedDeviceSpecificAction(String title, IDevice device) { - super(title); - this.device = device; - } - - @Override - public void setDevice(IDevice device) { - this.device = device; - } - - @Override - public void actionPerformed(ActionEvent e) { - if (device == null) { - return; - } - super.actionPerformed(e); - } -} diff --git a/tools/preload2/src/com/android/preload/actions/ClearTableAction.java b/tools/preload2/src/com/android/preload/actions/ClearTableAction.java deleted file mode 100644 index c0e4795b6d90..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ClearTableAction.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.preload.DumpTableModel; - -import java.awt.event.ActionEvent; - -import javax.swing.AbstractAction; - -public class ClearTableAction extends AbstractAction { - private final DumpTableModel dataTableModel; - - public ClearTableAction(DumpTableModel dataTableModel) { - super("Clear"); - this.dataTableModel = dataTableModel; - } - - @Override - public void actionPerformed(ActionEvent e) { - dataTableModel.clear(); - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java b/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java deleted file mode 100644 index 3a7f7f74d755..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ComputeThresholdAction.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.preload.DumpData; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -import java.awt.event.ActionEvent; -import java.io.File; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.regex.Pattern; - -import javax.swing.AbstractAction; - -/** - * Compute an intersection of classes from the given data. A class is in the intersection if it - * appears in at least the number of threshold given packages. An optional blacklist can be - * used to filter classes from the intersection. - */ -public class ComputeThresholdAction extends AbstractThreadedAction { - protected int threshold; - private Pattern blacklist; - private DumpTableModel dataTableModel; - - /** - * Create an action with the given parameters. The blacklist is a regular expression - * that filters classes. - */ - public ComputeThresholdAction(String name, DumpTableModel dataTableModel, int threshold, - String blacklist) { - super(name); - this.dataTableModel = dataTableModel; - this.threshold = threshold; - if (blacklist != null) { - this.blacklist = Pattern.compile(blacklist); - } - } - - @Override - public void actionPerformed(ActionEvent e) { - List<DumpData> data = dataTableModel.getData(); - if (data.size() == 0) { - Main.getUI().showMessageDialog("No data available, please scan packages or run " - + "monkeys."); - return; - } - if (data.size() == 1) { - Main.getUI().showMessageDialog("Cannot compute list from only one data set, please " - + "scan packages or run monkeys."); - return; - } - - super.actionPerformed(e); - } - - @Override - public void run() { - Main.getUI().showWaitDialog(); - - Map<String, Set<String>> uses = new HashMap<String, Set<String>>(); - for (DumpData d : dataTableModel.getData()) { - Main.getUI().updateWaitDialog("Merging " + d.getPackageName()); - updateClassUse(d.getPackageName(), uses, getBootClassPathClasses(d.getDumpData())); - } - - Main.getUI().updateWaitDialog("Computing thresholded set"); - Set<String> result = fromThreshold(uses, blacklist, threshold); - Main.getUI().hideWaitDialog(); - - boolean ret = Main.getUI().showConfirmDialog("Computed a set with " + result.size() - + " classes, would you like to save to disk?", "Save?"); - if (ret) { - File f = Main.getUI().showSaveDialog(); - if (f != null) { - saveSet(result, f); - } - } - } - - private Set<String> fromThreshold(Map<String, Set<String>> classUses, Pattern blacklist, - int threshold) { - TreeSet<String> ret = new TreeSet<>(); // TreeSet so it's nicely ordered by name. - - for (Map.Entry<String, Set<String>> e : classUses.entrySet()) { - if (e.getValue().size() >= threshold) { - if (blacklist == null || !blacklist.matcher(e.getKey()).matches()) { - ret.add(e.getKey()); - } - } - } - - return ret; - } - - private static void updateClassUse(String pkg, Map<String, Set<String>> classUses, - Set<String> classes) { - for (String className : classes) { - Set<String> old = classUses.get(className); - if (old == null) { - classUses.put(className, new HashSet<String>()); - } - classUses.get(className).add(pkg); - } - } - - private static Set<String> getBootClassPathClasses(Map<String, String> source) { - Set<String> ret = new HashSet<>(); - for (Map.Entry<String, String> e : source.entrySet()) { - if (e.getValue() == null) { - ret.add(e.getKey()); - } - } - return ret; - } - - private static void saveSet(Set<String> result, File f) { - try { - PrintWriter out = new PrintWriter(f); - for (String s : result) { - out.println(s); - } - out.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/ComputeThresholdXAction.java b/tools/preload2/src/com/android/preload/actions/ComputeThresholdXAction.java deleted file mode 100644 index 3ec0a4c18db1..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ComputeThresholdXAction.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -public class ComputeThresholdXAction extends ComputeThresholdAction { - - public ComputeThresholdXAction(String name, DumpTableModel dataTableModel, - String blacklist) { - super(name, dataTableModel, 1, blacklist); - } - - @Override - public void run() { - String value = Main.getUI().showInputDialog("Threshold?"); - - if (value != null) { - try { - threshold = Integer.parseInt(value); - super.run(); - } catch (Exception exc) { - } - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/DeviceSpecific.java b/tools/preload2/src/com/android/preload/actions/DeviceSpecific.java deleted file mode 100644 index 35a8f26a99fe..000000000000 --- a/tools/preload2/src/com/android/preload/actions/DeviceSpecific.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.ddmlib.IDevice; - -/** - * Marks an action as being device-specific. The user must set the device through the specified - * method if the device selection changes. - * - * Implementors must tolerate a null device (for example, with a no-op). This includes calling - * any methods before setDevice has been called. - */ -public interface DeviceSpecific { - - /** - * Set the device that should be used. Note that there is no restriction on calling other - * methods of the implementor before a setDevice call. Neither is device guaranteed to be - * non-null. - * - * @param device The device to use going forward. - */ - public void setDevice(IDevice device); -} diff --git a/tools/preload2/src/com/android/preload/actions/ExportAction.java b/tools/preload2/src/com/android/preload/actions/ExportAction.java deleted file mode 100644 index 848a56826788..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ExportAction.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.preload.DumpDataIO; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; -import java.awt.event.ActionEvent; -import java.io.File; -import java.io.PrintWriter; - -public class ExportAction extends AbstractThreadedAction { - private File lastSaveFile; - private DumpTableModel dataTableModel; - - public ExportAction(DumpTableModel dataTableModel) { - super("Export data"); - this.dataTableModel = dataTableModel; - } - - @Override - public void actionPerformed(ActionEvent e) { - lastSaveFile = Main.getUI().showSaveDialog(); - if (lastSaveFile != null) { - super.actionPerformed(e); - } - } - - @Override - public void run() { - Main.getUI().showWaitDialog(); - - String serialized = DumpDataIO.serialize(dataTableModel.getData()); - - if (serialized != null) { - try { - PrintWriter out = new PrintWriter(lastSaveFile); - out.println(serialized); - out.close(); - - Main.getUI().hideWaitDialog(); - } catch (Exception e) { - Main.getUI().hideWaitDialog(); - Main.getUI().showMessageDialog("Failed writing: " + e.getMessage()); - } - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/ImportAction.java b/tools/preload2/src/com/android/preload/actions/ImportAction.java deleted file mode 100644 index bfeeb836fd45..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ImportAction.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.preload.DumpData; -import com.android.preload.DumpDataIO; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -import java.awt.event.ActionEvent; -import java.io.File; -import java.util.Collection; - -import javax.swing.AbstractAction; - -public class ImportAction extends AbstractThreadedAction { - private File[] lastOpenFiles; - private DumpTableModel dataTableModel; - - public ImportAction(DumpTableModel dataTableModel) { - super("Import data"); - this.dataTableModel = dataTableModel; - } - - @Override - public void actionPerformed(ActionEvent e) { - lastOpenFiles = Main.getUI().showOpenDialog(true); - if (lastOpenFiles != null) { - super.actionPerformed(e); - } - } - - @Override - public void run() { - Main.getUI().showWaitDialog(); - - try { - for (File f : lastOpenFiles) { - try { - Collection<DumpData> data = DumpDataIO.deserialize(f); - - for (DumpData d : data) { - dataTableModel.addData(d); - } - } catch (Exception e) { - Main.getUI().showMessageDialog("Failed reading: " + e.getMessage()); - } - } - } finally { - Main.getUI().hideWaitDialog(); - } - - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/ReloadListAction.java b/tools/preload2/src/com/android/preload/actions/ReloadListAction.java deleted file mode 100644 index 29f055700dfa..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ReloadListAction.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.preload.ClientUtils; - -import java.util.Arrays; -import java.util.Comparator; - -import javax.swing.DefaultListModel; - -public class ReloadListAction extends AbstractThreadedDeviceSpecificAction { - - private ClientUtils clientUtils; - private final DefaultListModel<Client> clientListModel; - - public ReloadListAction(ClientUtils utils, IDevice device, - DefaultListModel<Client> clientListModel) { - super("Reload", device); - this.clientUtils = utils; - this.clientListModel = clientListModel; - } - - @Override - public void run() { - Client[] clients = clientUtils.findAllClients(device); - if (clients != null) { - Arrays.sort(clients, new ClientComparator()); - } - clientListModel.removeAllElements(); - for (Client c : clients) { - clientListModel.addElement(c); - } - } - - private static class ClientComparator implements Comparator<Client> { - - @Override - public int compare(Client o1, Client o2) { - String s1 = o1.getClientData().getClientDescription(); - String s2 = o2.getClientData().getClientDescription(); - - if (s1 == null || s2 == null) { - // Not good, didn't get all data? - return (s1 == null) ? -1 : 1; - } - - return s1.compareTo(s2); - } - - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/RunMonkeyAction.java b/tools/preload2/src/com/android/preload/actions/RunMonkeyAction.java deleted file mode 100644 index 29464fc7abdf..000000000000 --- a/tools/preload2/src/com/android/preload/actions/RunMonkeyAction.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.ddmlib.IDevice; -import com.android.preload.DeviceUtils; -import com.android.preload.DumpData; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -import java.awt.event.ActionEvent; -import java.util.Date; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.swing.AbstractAction; - -public class RunMonkeyAction extends AbstractAction implements DeviceSpecific { - - private final static String DEFAULT_MONKEY_PACKAGES = - "com.android.calendar,com.android.gallery3d"; - - private IDevice device; - private DumpTableModel dataTableModel; - - public RunMonkeyAction(IDevice device, DumpTableModel dataTableModel) { - super("Run monkey"); - this.device = device; - this.dataTableModel = dataTableModel; - } - - @Override - public void setDevice(IDevice device) { - this.device = device; - } - - @Override - public void actionPerformed(ActionEvent e) { - String packages = Main.getUI().showInputDialog("Please enter packages name to run with" - + " the monkey, or leave empty for default."); - if (packages == null) { - return; - } - if (packages.isEmpty()) { - packages = DEFAULT_MONKEY_PACKAGES; - } - Runnable r = new RunMonkeyRunnable(packages); - if (Main.getUI().isSingleThreaded()) { - r.run(); - } else { - new Thread(r).start(); - } - } - - private class RunMonkeyRunnable implements Runnable { - - private String packages; - private final static int ITERATIONS = 1000; - - public RunMonkeyRunnable(String packages) { - this.packages = packages; - } - - @Override - public void run() { - Main.getUI().showWaitDialog(); - - try { - String pkgs[] = packages.split(","); - - for (String pkg : pkgs) { - Main.getUI().updateWaitDialog("Running monkey on " + pkg); - - try { - // Stop running app. - forceStop(pkg); - - // Little bit of breather here. - try { - Thread.sleep(1000); - } catch (Exception e) { - } - - DeviceUtils.doShell(device, "monkey -p " + pkg + " " + ITERATIONS, 1, - TimeUnit.MINUTES); - - Main.getUI().updateWaitDialog("Retrieving heap data for " + pkg); - Map<String, String> data = Main.findAndGetClassData(device, pkg); - DumpData dumpData = new DumpData(pkg, data, new Date()); - dataTableModel.addData(dumpData); - } catch (Exception e) { - e.printStackTrace(); - } finally { - // Stop running app. - forceStop(pkg); - } - } - } finally { - Main.getUI().hideWaitDialog(); - } - } - - private void forceStop(String packageName) { - // Stop running app. - DeviceUtils.doShell(device, "force-stop " + packageName, 5, TimeUnit.SECONDS); - DeviceUtils.doShell(device, "kill " + packageName, 5, TimeUnit.SECONDS); - DeviceUtils.doShell(device, "kill `pid " + packageName + "`", 5, TimeUnit.SECONDS); - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/ScanAllPackagesAction.java b/tools/preload2/src/com/android/preload/actions/ScanAllPackagesAction.java deleted file mode 100644 index d74b8a3f6cfb..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ScanAllPackagesAction.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.preload.ClientUtils; -import com.android.preload.DumpData; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -import java.util.Date; -import java.util.Map; - -public class ScanAllPackagesAction extends AbstractThreadedDeviceSpecificAction { - - private ClientUtils clientUtils; - private DumpTableModel dataTableModel; - - public ScanAllPackagesAction(ClientUtils utils, IDevice device, DumpTableModel dataTableModel) { - super("Scan all packages", device); - this.clientUtils = utils; - this.dataTableModel = dataTableModel; - } - - @Override - public void run() { - Main.getUI().showWaitDialog(); - - try { - Client[] clients = clientUtils.findAllClients(device); - for (Client c : clients) { - String pkg = c.getClientData().getClientDescription(); - Main.getUI().showWaitDialog(); - Main.getUI().updateWaitDialog("Retrieving heap data for " + pkg); - - try { - Map<String, String> data = Main.getClassDataRetriever().getClassData(c); - DumpData dumpData = new DumpData(pkg, data, new Date()); - dataTableModel.addData(dumpData); - } catch (Exception e) { - e.printStackTrace(); - } - } - } finally { - Main.getUI().hideWaitDialog(); - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/ScanPackageAction.java b/tools/preload2/src/com/android/preload/actions/ScanPackageAction.java deleted file mode 100644 index 98492bd951bf..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ScanPackageAction.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.preload.ClientUtils; -import com.android.preload.DumpData; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -import java.util.Date; -import java.util.Map; - -public class ScanPackageAction extends AbstractThreadedDeviceSpecificAction { - - private ClientUtils clientUtils; - private DumpTableModel dataTableModel; - - public ScanPackageAction(ClientUtils utils, IDevice device, DumpTableModel dataTableModel) { - super("Scan package", device); - this.clientUtils = utils; - this.dataTableModel = dataTableModel; - } - - @Override - public void run() { - Main.getUI().showWaitDialog(); - - try { - Client client = Main.getUI().getSelectedClient(); - if (client != null) { - work(client); - } else { - Client[] clients = clientUtils.findAllClients(device); - if (clients.length > 0) { - ClientWrapper[] clientWrappers = new ClientWrapper[clients.length]; - for (int i = 0; i < clientWrappers.length; i++) { - clientWrappers[i] = new ClientWrapper(clients[i]); - } - Main.getUI().hideWaitDialog(); - - ClientWrapper ret = Main.getUI().showChoiceDialog("Choose a package to scan", - "Choose package", - clientWrappers); - if (ret != null) { - work(ret.client); - } - } - } - } finally { - Main.getUI().hideWaitDialog(); - } - } - - private void work(Client c) { - String pkg = c.getClientData().getClientDescription(); - Main.getUI().showWaitDialog(); - Main.getUI().updateWaitDialog("Retrieving heap data for " + pkg); - - try { - Map<String, String> data = Main.findAndGetClassData(device, pkg); - DumpData dumpData = new DumpData(pkg, data, new Date()); - dataTableModel.addData(dumpData); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static class ClientWrapper { - private Client client; - - public ClientWrapper(Client c) { - client = c; - } - - @Override - public String toString() { - return client.getClientData().getClientDescription() + " (pid " - + client.getClientData().getPid() + ")"; - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/ShowDataAction.java b/tools/preload2/src/com/android/preload/actions/ShowDataAction.java deleted file mode 100644 index 2bb175f60772..000000000000 --- a/tools/preload2/src/com/android/preload/actions/ShowDataAction.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.preload.DumpData; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.swing.AbstractAction; -import javax.swing.JFrame; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -public class ShowDataAction extends AbstractAction { - private DumpTableModel dataTableModel; - - public ShowDataAction(DumpTableModel dataTableModel) { - super("Show data"); - this.dataTableModel = dataTableModel; - } - - @Override - public void actionPerformed(ActionEvent e) { - // TODO(agampe): Auto-generated method stub - int selRow = Main.getUI().getSelectedDataTableRow(); - if (selRow != -1) { - DumpData data = dataTableModel.getData().get(selRow); - Map<String, Set<String>> inv = data.invertData(); - - StringBuilder builder = new StringBuilder(); - - // First bootclasspath. - add(builder, "Boot classpath:", inv.get(null)); - - // Now everything else. - for (String k : inv.keySet()) { - if (k != null) { - builder.append("==================\n\n"); - add(builder, k, inv.get(k)); - } - } - - JFrame newFrame = new JFrame(data.getPackageName() + " " + data.getDate()); - newFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); - newFrame.getContentPane().add(new JScrollPane(new JTextArea(builder.toString())), - BorderLayout.CENTER); - newFrame.setSize(800, 600); - newFrame.setLocationRelativeTo(null); - newFrame.setVisible(true); - } - } - - private void add(StringBuilder builder, String head, Set<String> set) { - builder.append(head); - builder.append('\n'); - addSet(builder, set); - builder.append('\n'); - } - - private void addSet(StringBuilder builder, Set<String> set) { - if (set == null) { - builder.append(" NONE\n"); - return; - } - List<String> sorted = new ArrayList<>(set); - Collections.sort(sorted); - for (String s : sorted) { - builder.append(s); - builder.append('\n'); - } - } -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/actions/WritePreloadedClassesAction.java b/tools/preload2/src/com/android/preload/actions/WritePreloadedClassesAction.java deleted file mode 100644 index 9b97f1168df9..000000000000 --- a/tools/preload2/src/com/android/preload/actions/WritePreloadedClassesAction.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.actions; - -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.preload.ClientUtils; -import com.android.preload.DeviceUtils; -import com.android.preload.DumpData; -import com.android.preload.DumpTableModel; -import com.android.preload.Main; - -import java.awt.event.ActionEvent; -import java.io.File; -import java.util.Date; -import java.util.Map; - -public class WritePreloadedClassesAction extends AbstractThreadedDeviceSpecificAction { - private File preloadedClassFile; - - public WritePreloadedClassesAction(ClientUtils utils, IDevice device, DumpTableModel dataTableModel) { - super("Write preloaded classes action", device); - } - - @Override - public void actionPerformed(ActionEvent e) { - File[] files = Main.getUI().showOpenDialog(true); - if (files != null && files.length > 0) { - preloadedClassFile = files[0]; - super.actionPerformed(e); - } - } - - @Override - public void run() { - Main.getUI().showWaitDialog(); - try { - // Write the new file with a 5-minute timeout - DeviceUtils.overwritePreloaded(device, preloadedClassFile, 5 * 60); - } catch (Exception e) { - System.err.println(e); - } finally { - Main.getUI().hideWaitDialog(); - } - } -} diff --git a/tools/preload2/src/com/android/preload/classdataretrieval/hprof/GeneralHprofDumpHandler.java b/tools/preload2/src/com/android/preload/classdataretrieval/hprof/GeneralHprofDumpHandler.java deleted file mode 100644 index 8d797ee00128..000000000000 --- a/tools/preload2/src/com/android/preload/classdataretrieval/hprof/GeneralHprofDumpHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.classdataretrieval.hprof; - -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData.IHprofDumpHandler; - -import java.util.ArrayList; -import java.util.List; - -public class GeneralHprofDumpHandler implements IHprofDumpHandler { - - private List<IHprofDumpHandler> handlers = new ArrayList<>(); - - public void addHandler(IHprofDumpHandler h) { - synchronized (handlers) { - handlers.add(h); - } - } - - public void removeHandler(IHprofDumpHandler h) { - synchronized (handlers) { - handlers.remove(h); - } - } - - private List<IHprofDumpHandler> getIterationList() { - synchronized (handlers) { - return new ArrayList<>(handlers); - } - } - - @Override - public void onEndFailure(Client arg0, String arg1) { - List<IHprofDumpHandler> iterList = getIterationList(); - for (IHprofDumpHandler h : iterList) { - h.onEndFailure(arg0, arg1); - } - } - - @Override - public void onSuccess(String arg0, Client arg1) { - List<IHprofDumpHandler> iterList = getIterationList(); - for (IHprofDumpHandler h : iterList) { - h.onSuccess(arg0, arg1); - } - } - - @Override - public void onSuccess(byte[] arg0, Client arg1) { - List<IHprofDumpHandler> iterList = getIterationList(); - for (IHprofDumpHandler h : iterList) { - h.onSuccess(arg0, arg1); - } - } - }
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/classdataretrieval/hprof/Hprof.java b/tools/preload2/src/com/android/preload/classdataretrieval/hprof/Hprof.java deleted file mode 100644 index 84ec8b7d0fdd..000000000000 --- a/tools/preload2/src/com/android/preload/classdataretrieval/hprof/Hprof.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.classdataretrieval.hprof; - -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData; -import com.android.ddmlib.ClientData.IHprofDumpHandler; -import com.android.preload.classdataretrieval.ClassDataRetriever; -import com.android.preload.ui.NullProgressMonitor; -import com.android.tools.perflib.captures.MemoryMappedFileBuffer; -import com.android.tools.perflib.heap.ClassObj; -import com.android.tools.perflib.heap.Queries; -import com.android.tools.perflib.heap.Snapshot; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class Hprof implements ClassDataRetriever { - - private static GeneralHprofDumpHandler hprofHandler; - - public static void init() { - synchronized(Hprof.class) { - if (hprofHandler == null) { - ClientData.setHprofDumpHandler(hprofHandler = new GeneralHprofDumpHandler()); - } - } - } - - public static File doHprof(Client client, int timeout) { - GetHprof gh = new GetHprof(client, timeout); - return gh.get(); - } - - /** - * Return a map of class names to class-loader names derived from the hprof dump. - * - * @param hprofLocalFile - */ - public static Map<String, String> analyzeHprof(File hprofLocalFile) throws Exception { - Snapshot snapshot = Snapshot.createSnapshot(new MemoryMappedFileBuffer(hprofLocalFile)); - - Map<String, Set<ClassObj>> classes = Queries.classes(snapshot, null); - Map<String, String> retValue = new HashMap<String, String>(); - for (Map.Entry<String, Set<ClassObj>> e : classes.entrySet()) { - for (ClassObj c : e.getValue()) { - String cl = c.getClassLoader() == null ? null : c.getClassLoader().toString(); - String cName = c.getClassName(); - int aDepth = 0; - while (cName.endsWith("[]")) { - cName = cName.substring(0, cName.length()-2); - aDepth++; - } - String newName = transformPrimitiveClass(cName); - if (aDepth > 0) { - // Need to use kind-a descriptor syntax. If it was transformed, it is primitive. - if (newName.equals(cName)) { - newName = "L" + newName + ";"; - } - for (int i = 0; i < aDepth; i++) { - newName = "[" + newName; - } - } - retValue.put(newName, cl); - } - } - - // Free up memory. - snapshot.dispose(); - - return retValue; - } - - private static Map<String, String> primitiveMapping; - - static { - primitiveMapping = new HashMap<>(); - primitiveMapping.put("boolean", "Z"); - primitiveMapping.put("byte", "B"); - primitiveMapping.put("char", "C"); - primitiveMapping.put("double", "D"); - primitiveMapping.put("float", "F"); - primitiveMapping.put("int", "I"); - primitiveMapping.put("long", "J"); - primitiveMapping.put("short", "S"); - primitiveMapping.put("void", "V"); - } - - private static String transformPrimitiveClass(String name) { - String rep = primitiveMapping.get(name); - if (rep != null) { - return rep; - } - return name; - } - - private static class GetHprof implements IHprofDumpHandler { - - private File target; - private long timeout; - private Client client; - - public GetHprof(Client client, long timeout) { - this.client = client; - this.timeout = timeout; - } - - public File get() { - synchronized (this) { - hprofHandler.addHandler(this); - client.dumpHprof(); - if (target == null) { - try { - wait(timeout); - } catch (Exception e) { - System.out.println(e); - } - } - } - - hprofHandler.removeHandler(this); - return target; - } - - private void wakeUp() { - synchronized (this) { - notifyAll(); - } - } - - @Override - public void onEndFailure(Client arg0, String arg1) { - System.out.println("GetHprof.onEndFailure"); - if (client == arg0) { - wakeUp(); - } - } - - private static File createTargetFile() { - try { - return File.createTempFile("ddms", ".hprof"); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public void onSuccess(String arg0, Client arg1) { - System.out.println("GetHprof.onSuccess"); - if (client == arg1) { - try { - target = createTargetFile(); - arg1.getDevice().getSyncService().pullFile(arg0, - target.getAbsoluteFile().toString(), new NullProgressMonitor()); - } catch (Exception e) { - if (target != null) { - target.delete(); - } - e.printStackTrace(); - target = null; - } - wakeUp(); - } - } - - @Override - public void onSuccess(byte[] arg0, Client arg1) { - System.out.println("GetHprof.onSuccess"); - if (client == arg1) { - try { - target = createTargetFile(); - BufferedOutputStream out = - new BufferedOutputStream(new FileOutputStream(target)); - out.write(arg0); - out.close(); - } catch (Exception e) { - if (target != null) { - target.delete(); - } - e.printStackTrace(); - target = null; - } - wakeUp(); - } - } - } - - private int timeout; - - public Hprof(int timeout) { - this.timeout = timeout; - } - - @Override - public Map<String, String> getClassData(Client client) { - File hprofLocalFile = Hprof.doHprof(client, timeout); - if (hprofLocalFile == null) { - throw new RuntimeException("Failed getting dump..."); - } - System.out.println("Dump file is " + hprofLocalFile); - - try { - return analyzeHprof(hprofLocalFile); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - hprofLocalFile.delete(); - } - } -} diff --git a/tools/preload2/src/com/android/preload/classdataretrieval/jdwp/JDWPClassDataRetriever.java b/tools/preload2/src/com/android/preload/classdataretrieval/jdwp/JDWPClassDataRetriever.java deleted file mode 100644 index dbd4c89b27cf..000000000000 --- a/tools/preload2/src/com/android/preload/classdataretrieval/jdwp/JDWPClassDataRetriever.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.classdataretrieval.jdwp; - -import com.android.ddmlib.Client; -import com.android.preload.classdataretrieval.ClassDataRetriever; - -import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; -import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; -import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; -import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; -import org.apache.harmony.jpda.tests.jdwp.share.JDWPTestCase; -import org.apache.harmony.jpda.tests.jdwp.share.JDWPUnitDebuggeeWrapper; -import org.apache.harmony.jpda.tests.share.JPDALogWriter; -import org.apache.harmony.jpda.tests.share.JPDATestOptions; - -import java.util.HashMap; -import java.util.Map; - -public class JDWPClassDataRetriever extends JDWPTestCase implements ClassDataRetriever { - - private final Client client; - - public JDWPClassDataRetriever() { - this(null); - } - - public JDWPClassDataRetriever(Client client) { - this.client = client; - } - - - @Override - protected String getDebuggeeClassName() { - return "<unset>"; - } - - @Override - public Map<String, String> getClassData(Client client) { - return new JDWPClassDataRetriever(client).retrieve(); - } - - private Map<String, String> retrieve() { - if (client == null) { - throw new IllegalStateException(); - } - - settings = createTestOptions("localhost:" + String.valueOf(client.getDebuggerListenPort())); - settings.setDebuggeeSuspend("n"); - - logWriter = new JPDALogWriter(System.out, "", false); - - try { - internalSetUp(); - - return retrieveImpl(); - } catch (Exception e) { - e.printStackTrace(); - return null; - } finally { - internalTearDown(); - } - } - - private Map<String, String> retrieveImpl() { - try { - // Suspend the app. - { - CommandPacket packet = new CommandPacket( - JDWPCommands.VirtualMachineCommandSet.CommandSetID, - JDWPCommands.VirtualMachineCommandSet.SuspendCommand); - ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); - if (reply.getErrorCode() != JDWPConstants.Error.NONE) { - return null; - } - } - - // List all classes. - CommandPacket packet = new CommandPacket( - JDWPCommands.VirtualMachineCommandSet.CommandSetID, - JDWPCommands.VirtualMachineCommandSet.AllClassesCommand); - ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); - - if (reply.getErrorCode() != JDWPConstants.Error.NONE) { - return null; - } - - int classCount = reply.getNextValueAsInt(); - System.out.println("Runtime reported " + classCount + " classes."); - - Map<Long, String> classes = new HashMap<Long, String>(); - Map<Long, String> arrayClasses = new HashMap<Long, String>(); - - for (int i = 0; i < classCount; i++) { - byte refTypeTag = reply.getNextValueAsByte(); - long typeID = reply.getNextValueAsReferenceTypeID(); - String signature = reply.getNextValueAsString(); - /* int status = */ reply.getNextValueAsInt(); - - switch (refTypeTag) { - case JDWPConstants.TypeTag.CLASS: - case JDWPConstants.TypeTag.INTERFACE: - classes.put(typeID, signature); - break; - - case JDWPConstants.TypeTag.ARRAY: - arrayClasses.put(typeID, signature); - break; - } - } - - Map<String, String> result = new HashMap<String, String>(); - - // Parse all classes. - for (Map.Entry<Long, String> entry : classes.entrySet()) { - long typeID = entry.getKey(); - String signature = entry.getValue(); - - if (!checkClass(typeID, signature, result)) { - System.err.println("Issue investigating " + signature); - } - } - - // For arrays, look at the leaf component type. - for (Map.Entry<Long, String> entry : arrayClasses.entrySet()) { - long typeID = entry.getKey(); - String signature = entry.getValue(); - - if (!checkArrayClass(typeID, signature, result)) { - System.err.println("Issue investigating " + signature); - } - } - - return result; - } finally { - // Resume the app. - { - CommandPacket packet = new CommandPacket( - JDWPCommands.VirtualMachineCommandSet.CommandSetID, - JDWPCommands.VirtualMachineCommandSet.ResumeCommand); - /* ReplyPacket reply = */ debuggeeWrapper.vmMirror.performCommand(packet); - } - } - } - - private boolean checkClass(long typeID, String signature, Map<String, String> result) { - CommandPacket packet = new CommandPacket( - JDWPCommands.ReferenceTypeCommandSet.CommandSetID, - JDWPCommands.ReferenceTypeCommandSet.ClassLoaderCommand); - packet.setNextValueAsReferenceTypeID(typeID); - ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); - if (reply.getErrorCode() != JDWPConstants.Error.NONE) { - return false; - } - - long classLoaderID = reply.getNextValueAsObjectID(); - - // TODO: Investigate the classloader to have a better string? - String classLoaderString = (classLoaderID == 0) ? null : String.valueOf(classLoaderID); - - result.put(getClassName(signature), classLoaderString); - - return true; - } - - private boolean checkArrayClass(long typeID, String signature, Map<String, String> result) { - // Classloaders of array classes are the same as the component class'. - CommandPacket packet = new CommandPacket( - JDWPCommands.ReferenceTypeCommandSet.CommandSetID, - JDWPCommands.ReferenceTypeCommandSet.ClassLoaderCommand); - packet.setNextValueAsReferenceTypeID(typeID); - ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); - if (reply.getErrorCode() != JDWPConstants.Error.NONE) { - return false; - } - - long classLoaderID = reply.getNextValueAsObjectID(); - - // TODO: Investigate the classloader to have a better string? - String classLoaderString = (classLoaderID == 0) ? null : String.valueOf(classLoaderID); - - // For array classes, we *need* the signature directly. - result.put(signature, classLoaderString); - - return true; - } - - private static String getClassName(String signature) { - String withoutLAndSemicolon = signature.substring(1, signature.length() - 1); - return withoutLAndSemicolon.replace('/', '.'); - } - - - private static JPDATestOptions createTestOptions(String address) { - JPDATestOptions options = new JPDATestOptions(); - options.setAttachConnectorKind(); - options.setTimeout(1000); - options.setWaitingTime(1000); - options.setTransportAddress(address); - return options; - } - - @Override - protected JDWPUnitDebuggeeWrapper createDebuggeeWrapper() { - return new PreloadDebugeeWrapper(settings, logWriter); - } -} diff --git a/tools/preload2/src/com/android/preload/classdataretrieval/jdwp/PreloadDebugeeWrapper.java b/tools/preload2/src/com/android/preload/classdataretrieval/jdwp/PreloadDebugeeWrapper.java deleted file mode 100644 index b9df6d0aeb93..000000000000 --- a/tools/preload2/src/com/android/preload/classdataretrieval/jdwp/PreloadDebugeeWrapper.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.classdataretrieval.jdwp; - -import org.apache.harmony.jpda.tests.framework.LogWriter; -import org.apache.harmony.jpda.tests.jdwp.share.JDWPManualDebuggeeWrapper; -import org.apache.harmony.jpda.tests.share.JPDATestOptions; - -import java.io.IOException; - -public class PreloadDebugeeWrapper extends JDWPManualDebuggeeWrapper { - - public PreloadDebugeeWrapper(JPDATestOptions options, LogWriter writer) { - super(options, writer); - } - - @Override - protected Process launchProcess(String cmdLine) throws IOException { - return null; - } - - @Override - protected void WaitForProcessExit(Process process) { - } - -} diff --git a/tools/preload2/src/com/android/preload/ui/IUI.java b/tools/preload2/src/com/android/preload/ui/IUI.java deleted file mode 100644 index 9371463e9a79..000000000000 --- a/tools/preload2/src/com/android/preload/ui/IUI.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.android.preload.ui; - -import com.android.ddmlib.Client; -import java.io.File; -import java.util.List; -import javax.swing.Action; -import javax.swing.ListModel; -import javax.swing.table.TableModel; - -/** - * UI abstraction for the tool. This allows a graphical mode, command line mode, - * or silent mode. - */ -public interface IUI { - - void prepare(ListModel<Client> clientListModel, TableModel dataTableModel, - List<Action> actions); - - void ready(); - - boolean isSingleThreaded(); - - Client getSelectedClient(); - - int getSelectedDataTableRow(); - - void showWaitDialog(); - - void updateWaitDialog(String s); - - void hideWaitDialog(); - - void showMessageDialog(String s); - - boolean showConfirmDialog(String title, String message); - - String showInputDialog(String message); - - <T> T showChoiceDialog(String title, String message, T[] choices); - - File showSaveDialog(); - - File[] showOpenDialog(boolean multi); - -} diff --git a/tools/preload2/src/com/android/preload/ui/NullProgressMonitor.java b/tools/preload2/src/com/android/preload/ui/NullProgressMonitor.java deleted file mode 100644 index f45aad06ac6b..000000000000 --- a/tools/preload2/src/com/android/preload/ui/NullProgressMonitor.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.ui; - -import com.android.ddmlib.SyncService.ISyncProgressMonitor; - -public class NullProgressMonitor implements ISyncProgressMonitor { - - @Override - public void advance(int arg0) {} - - @Override - public boolean isCanceled() { - return false; - } - - @Override - public void start(int arg0) {} - - @Override - public void startSubTask(String arg0) {} - - @Override - public void stop() {} -}
\ No newline at end of file diff --git a/tools/preload2/src/com/android/preload/ui/SequenceUI.java b/tools/preload2/src/com/android/preload/ui/SequenceUI.java deleted file mode 100644 index dc6a4f389b10..000000000000 --- a/tools/preload2/src/com/android/preload/ui/SequenceUI.java +++ /dev/null @@ -1,222 +0,0 @@ -package com.android.preload.ui; - -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData; -import java.io.File; -import java.util.LinkedList; -import java.util.List; -import javax.swing.Action; -import javax.swing.ListModel; -import javax.swing.table.TableModel; - -public class SequenceUI implements IUI { - - private ListModel<Client> clientListModel; - @SuppressWarnings("unused") - private TableModel dataTableModel; - private List<Action> actions; - - private List<Object> sequence = new LinkedList<>(); - - public SequenceUI() { - } - - @Override - public boolean isSingleThreaded() { - return true; - } - - @Override - public void prepare(ListModel<Client> clientListModel, TableModel dataTableModel, - List<Action> actions) { - this.clientListModel = clientListModel; - this.dataTableModel = dataTableModel; - this.actions = actions; - } - - public SequenceUI action(Action a) { - sequence.add(a); - return this; - } - - public SequenceUI action(Class<? extends Action> actionClass) { - for (Action a : actions) { - if (actionClass.equals(a.getClass())) { - sequence.add(a); - return this; - } - } - throw new IllegalArgumentException("No action of class " + actionClass + " found."); - } - - public SequenceUI confirmYes() { - sequence.add(Boolean.TRUE); - return this; - } - - public SequenceUI confirmNo() { - sequence.add(Boolean.FALSE); - return this; - } - - public SequenceUI input(String input) { - sequence.add(input); - return this; - } - - public SequenceUI input(File... f) { - sequence.add(f); - return this; - } - - public SequenceUI output(File f) { - sequence.add(f); - return this; - } - - public SequenceUI tableRow(int i) { - sequence.add(i); - return this; - } - - private class ClientSelector { - private String pkg; - - public ClientSelector(String pkg) { - this.pkg = pkg; - } - - public Client getClient() { - for (int i = 0; i < clientListModel.getSize(); i++) { - ClientData cd = clientListModel.getElementAt(i).getClientData(); - if (cd != null) { - String s = cd.getClientDescription(); - if (pkg.equals(s)) { - return clientListModel.getElementAt(i); - } - } - } - throw new RuntimeException("Didn't find client " + pkg); - } - } - - public SequenceUI client(String pkg) { - sequence.add(new ClientSelector(pkg)); - return this; - } - - public SequenceUI choice(String pattern) { - sequence.add(pattern); - return this; - } - - @Override - public void ready() { - // Run the actions. - // No iterator or foreach loop as the sequence will be emptied while running. - try { - while (!sequence.isEmpty()) { - Object next = sequence.remove(0); - if (next instanceof Action) { - ((Action)next).actionPerformed(null); - } else { - throw new IllegalStateException("Didn't expect a non-action: " + next); - } - } - } catch (Exception e) { - e.printStackTrace(System.out); - } - - // Now shut down. - System.exit(0); - } - - @Override - public Client getSelectedClient() { - Object next = sequence.remove(0); - if (next instanceof ClientSelector) { - return ((ClientSelector)next).getClient(); - } - throw new IllegalStateException("Unexpected: " + next); - } - - @Override - public int getSelectedDataTableRow() { - Object next = sequence.remove(0); - if (next instanceof Integer) { - return ((Integer)next).intValue(); - } - throw new IllegalStateException("Unexpected: " + next); - } - - @Override - public void showWaitDialog() { - } - - @Override - public void updateWaitDialog(String s) { - System.out.println(s); - } - - @Override - public void hideWaitDialog() { - } - - @Override - public void showMessageDialog(String s) { - System.out.println(s); - } - - @Override - public boolean showConfirmDialog(String title, String message) { - Object next = sequence.remove(0); - if (next instanceof Boolean) { - return ((Boolean)next).booleanValue(); - } - throw new IllegalStateException("Unexpected: " + next); - } - - @Override - public String showInputDialog(String message) { - Object next = sequence.remove(0); - if (next instanceof String) { - return (String)next; - } - throw new IllegalStateException("Unexpected: " + next); - } - - @Override - public <T> T showChoiceDialog(String title, String message, T[] choices) { - Object next = sequence.remove(0); - if (next instanceof String) { - String s = (String)next; - for (T t : choices) { - if (t.toString().contains(s)) { - return t; - } - } - return null; - } - throw new IllegalStateException("Unexpected: " + next); - } - - @Override - public File showSaveDialog() { - Object next = sequence.remove(0); - if (next instanceof File) { - System.out.println(next); - return (File)next; - } - throw new IllegalStateException("Unexpected: " + next); - } - - @Override - public File[] showOpenDialog(boolean multi) { - Object next = sequence.remove(0); - if (next instanceof File[]) { - return (File[])next; - } - throw new IllegalStateException("Unexpected: " + next); - } - -} diff --git a/tools/preload2/src/com/android/preload/ui/SwingUI.java b/tools/preload2/src/com/android/preload/ui/SwingUI.java deleted file mode 100644 index cab3744ad74c..000000000000 --- a/tools/preload2/src/com/android/preload/ui/SwingUI.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.preload.ui; - -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.io.File; -import java.util.List; - -import javax.swing.Action; -import javax.swing.DefaultListCellRenderer; -import javax.swing.JDialog; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JProgressBar; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JToolBar; -import javax.swing.ListModel; -import javax.swing.SwingUtilities; -import javax.swing.table.TableModel; - -public class SwingUI extends JFrame implements IUI { - - private JList<Client> clientList; - private JTable dataTable; - - // Shared file chooser, means the directory is retained. - private JFileChooser jfc; - - public SwingUI() { - super("Preloaded-classes computation"); - } - - @Override - public boolean isSingleThreaded() { - return false; - } - - @Override - public void prepare(ListModel<Client> clientListModel, TableModel dataTableModel, - List<Action> actions) { - getContentPane().add(new JScrollPane(clientList = new JList<Client>(clientListModel)), - BorderLayout.WEST); - clientList.setCellRenderer(new ClientListCellRenderer()); - // clientList.addListSelectionListener(listener); - - dataTable = new JTable(dataTableModel); - getContentPane().add(new JScrollPane(dataTable), BorderLayout.CENTER); - - JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL); - for (Action a : actions) { - if (a == null) { - toolbar.addSeparator(); - } else { - toolbar.add(a); - } - } - getContentPane().add(toolbar, BorderLayout.PAGE_START); - - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - setBounds(100, 100, 800, 600); - - setVisible(true); - } - - @Override - public void ready() { - } - - @Override - public Client getSelectedClient() { - return clientList.getSelectedValue(); - } - - @Override - public int getSelectedDataTableRow() { - return dataTable.getSelectedRow(); - } - - private JDialog currentWaitDialog = null; - - @Override - public void showWaitDialog() { - if (currentWaitDialog == null) { - currentWaitDialog = new JDialog(this, "Please wait...", true); - currentWaitDialog.getContentPane().add(new JLabel("Please be patient."), - BorderLayout.CENTER); - JProgressBar progress = new JProgressBar(JProgressBar.HORIZONTAL); - progress.setIndeterminate(true); - currentWaitDialog.getContentPane().add(progress, BorderLayout.SOUTH); - currentWaitDialog.setSize(200, 100); - currentWaitDialog.setLocationRelativeTo(null); - showWaitDialogLater(); - } - } - - private void showWaitDialogLater() { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(true); // This is blocking. - } - } - }); - } - - @Override - public void updateWaitDialog(String s) { - if (currentWaitDialog != null) { - ((JLabel) currentWaitDialog.getContentPane().getComponent(0)).setText(s); - Dimension prefSize = currentWaitDialog.getPreferredSize(); - Dimension curSize = currentWaitDialog.getSize(); - if (prefSize.width > curSize.width || prefSize.height > curSize.height) { - currentWaitDialog.setSize(Math.max(prefSize.width, curSize.width), - Math.max(prefSize.height, curSize.height)); - currentWaitDialog.invalidate(); - } - } - } - - @Override - public void hideWaitDialog() { - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(false); - currentWaitDialog = null; - } - } - - @Override - public void showMessageDialog(String s) { - // Hide the wait dialog... - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(false); - } - - try { - JOptionPane.showMessageDialog(this, s); - } finally { - // And reshow it afterwards... - if (currentWaitDialog != null) { - showWaitDialogLater(); - } - } - } - - @Override - public boolean showConfirmDialog(String title, String message) { - // Hide the wait dialog... - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(false); - } - - try { - return JOptionPane.showConfirmDialog(this, title, message, JOptionPane.YES_NO_OPTION) - == JOptionPane.YES_OPTION; - } finally { - // And reshow it afterwards... - if (currentWaitDialog != null) { - showWaitDialogLater(); - } - } - } - - @Override - public String showInputDialog(String message) { - // Hide the wait dialog... - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(false); - } - - try { - return JOptionPane.showInputDialog(message); - } finally { - // And reshow it afterwards... - if (currentWaitDialog != null) { - showWaitDialogLater(); - } - } - } - - @Override - @SuppressWarnings("unchecked") - public <T> T showChoiceDialog(String title, String message, T[] choices) { - // Hide the wait dialog... - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(false); - } - - try{ - return (T)JOptionPane.showInputDialog(this, - title, - message, - JOptionPane.QUESTION_MESSAGE, - null, - choices, - choices[0]); - } finally { - // And reshow it afterwards... - if (currentWaitDialog != null) { - showWaitDialogLater(); - } - } - } - - @Override - public File showSaveDialog() { - // Hide the wait dialog... - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(false); - } - - try{ - if (jfc == null) { - jfc = new JFileChooser(); - } - - int ret = jfc.showSaveDialog(this); - if (ret == JFileChooser.APPROVE_OPTION) { - return jfc.getSelectedFile(); - } else { - return null; - } - } finally { - // And reshow it afterwards... - if (currentWaitDialog != null) { - showWaitDialogLater(); - } - } - } - - @Override - public File[] showOpenDialog(boolean multi) { - // Hide the wait dialog... - if (currentWaitDialog != null) { - currentWaitDialog.setVisible(false); - } - - try{ - if (jfc == null) { - jfc = new JFileChooser(); - } - - jfc.setMultiSelectionEnabled(multi); - int ret = jfc.showOpenDialog(this); - if (ret == JFileChooser.APPROVE_OPTION) { - return jfc.getSelectedFiles(); - } else { - return null; - } - } finally { - // And reshow it afterwards... - if (currentWaitDialog != null) { - showWaitDialogLater(); - } - } - } - - private class ClientListCellRenderer extends DefaultListCellRenderer { - - @Override - public Component getListCellRendererComponent(JList<?> list, Object value, int index, - boolean isSelected, boolean cellHasFocus) { - ClientData cd = ((Client) value).getClientData(); - String s = cd.getClientDescription() + " (pid " + cd.getPid() + ")"; - return super.getListCellRendererComponent(list, s, index, isSelected, cellHasFocus); - } - } -} |