diff options
70 files changed, 943 insertions, 1497 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 3fea8fc34d3c..55f5436eed90 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -18,6 +18,7 @@ java_defaults { // Add java_aconfig_libraries to here to add them to the core framework srcs: [ + ":android.os.flags-aconfig-java{.generated_srcjars}", ":android.security.flags-aconfig-java{.generated_srcjars}", ":com.android.hardware.camera2-aconfig-java{.generated_srcjars}", ":com.android.window.flags.window-aconfig-java{.generated_srcjars}", @@ -88,6 +89,19 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +// OS +aconfig_declarations { + name: "android.os.flags-aconfig", + package: "android.os", + srcs: ["core/java/android/os/*.aconfig"], +} + +java_aconfig_library { + name: "android.os.flags-aconfig-java", + aconfig_declarations: "android.os.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // Security aconfig_declarations { name: "android.security.flags-aconfig", @@ -28,7 +28,7 @@ per-file */TEST_MAPPING = * # Support bulk translation updates per-file */res*/values*/*.xml = byi@google.com, delphij@google.com -per-file **.bp,**.mk = hansson@google.com, joeo@google.com +per-file **.bp,**.mk = hansson@google.com, joeo@google.com, lamontjones@google.com per-file TestProtoLibraries.bp = file:platform/platform_testing:/libraries/health/OWNERS per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index fadf82afe858..0ed47e7da2c9 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -1790,7 +1790,7 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) { fn.c_str()); return nullptr; } - ZipFileRO *zip = ZipFileRO::open(fn); + ZipFileRO *zip = ZipFileRO::open(fn.c_str()); if (zip == nullptr) { SLOGE("Failed to open animation zip \"%s\": %s", fn.c_str(), strerror(errno)); diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index f41e57cc66d6..0862fbe78936 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -94,7 +94,7 @@ void PrintValue(AssetManager2* const am, const AssetManager2::SelectedValue& val const ResStringPool* pool = am->GetStringPoolForCookie(value.cookie); out->append("\""); if (auto str = pool->string8ObjectAt(value.data); str.ok()) { - out->append(*str); + out->append(str->c_str()); } } break; default: diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp index 53c7b744ee0f..82c87071bfff 100644 --- a/cmds/incidentd/src/IncidentService.cpp +++ b/cmds/incidentd/src/IncidentService.cpp @@ -563,7 +563,7 @@ status_t IncidentService::command(FILE* in, FILE* out, FILE* err, Vector<String8 fprintf(out, "Not enough arguments for section\n"); return NO_ERROR; } - int id = atoi(args[1]); + int id = atoi(args[1].c_str()); int idx = 0; while (SECTION_LIST[idx] != NULL) { const Section* section = SECTION_LIST[idx]; diff --git a/core/java/Android.bp b/core/java/Android.bp index 5d7d7ba2379c..da6a6d46c132 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -9,6 +9,11 @@ package { default_applicable_licenses: ["frameworks_base_license"], } +aidl_library { + name: "HardwareBuffer_aidl", + hdrs: ["android/hardware/HardwareBuffer.aidl"], +} + filegroup { name: "framework-core-sources", srcs: [ diff --git a/core/java/android/app/trust/ITrustListener.aidl b/core/java/android/app/trust/ITrustListener.aidl index e4ac01195bcb..8d4478493b13 100644 --- a/core/java/android/app/trust/ITrustListener.aidl +++ b/core/java/android/app/trust/ITrustListener.aidl @@ -24,6 +24,7 @@ import java.util.List; * {@hide} */ oneway interface ITrustListener { + void onEnabledTrustAgentsChanged(int userId); void onTrustChanged(boolean enabled, boolean newlyUnlocked, int userId, int flags, in List<String> trustGrantedMessages); void onTrustManagedChanged(boolean managed, int userId); diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java index 62f755d0268c..3552ce0e5889 100644 --- a/core/java/android/app/trust/TrustManager.java +++ b/core/java/android/app/trust/TrustManager.java @@ -43,6 +43,7 @@ public class TrustManager { private static final int MSG_TRUST_CHANGED = 1; private static final int MSG_TRUST_MANAGED_CHANGED = 2; private static final int MSG_TRUST_ERROR = 3; + private static final int MSG_ENABLED_TRUST_AGENTS_CHANGED = 4; private static final String TAG = "TrustManager"; private static final String DATA_FLAGS = "initiatedByUser"; @@ -187,6 +188,13 @@ public class TrustManager { } @Override + public void onEnabledTrustAgentsChanged(int userId) { + final Message m = mHandler.obtainMessage(MSG_ENABLED_TRUST_AGENTS_CHANGED, + userId, 0, trustListener); + m.sendToTarget(); + } + + @Override public void onTrustManagedChanged(boolean managed, int userId) { mHandler.obtainMessage(MSG_TRUST_MANAGED_CHANGED, (managed ? 1 : 0), userId, trustListener).sendToTarget(); @@ -283,6 +291,10 @@ public class TrustManager { case MSG_TRUST_ERROR: final CharSequence message = msg.peekData().getCharSequence(DATA_MESSAGE); ((TrustListener) msg.obj).onTrustError(message); + break; + case MSG_ENABLED_TRUST_AGENTS_CHANGED: + ((TrustListener) msg.obj).onEnabledTrustAgentsChanged(msg.arg1); + break; } } }; @@ -316,5 +328,10 @@ public class TrustManager { * @param message A message that should be displayed on the UI. */ void onTrustError(CharSequence message); + + /** + * Reports that the enabled trust agents for the specified user has changed. + */ + void onEnabledTrustAgentsChanged(int userId); } } diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig new file mode 100644 index 000000000000..851aa6dce560 --- /dev/null +++ b/core/java/android/os/flags.aconfig @@ -0,0 +1,8 @@ +package: "android.os" + +flag { + name: "disallow_cellular_null_ciphers_restriction" + namespace: "cellular_security" + description: "Guards a new UserManager user restriction that admins can use to require cellular encryption on their managed devices." + bug: "276752881" +} diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index b27dac2de6af..b6c2b83f0daa 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -6,3 +6,10 @@ flag { description: "Feature flag for fs-verity API" bug: "285185747" } + +flag { + name: "fix_unlocked_device_required_keys" + namespace: "hardware_backed_security" + description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys" + bug: "296464083" +} diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig new file mode 100644 index 000000000000..7a4c5bc669fc --- /dev/null +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -0,0 +1,8 @@ +package: "com.android.window.flags" + +flag { + name: "nav_bar_transparent_by_default" + namespace: "windowing_frontend" + description: "Make nav bar color transparent by default when targeting SDK 35 or greater" + bug: "232195501" +} diff --git a/core/java/com/android/internal/util/FileRotator.java b/core/java/com/android/internal/util/FileRotator.java index 5bc48c5172f0..c9d9926ba75a 100644 --- a/core/java/com/android/internal/util/FileRotator.java +++ b/core/java/com/android/internal/util/FileRotator.java @@ -19,6 +19,9 @@ package com.android.internal.util; import android.annotation.NonNull; import android.os.FileUtils; import android.util.Log; +import android.util.Pair; + +import libcore.io.IoUtils; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -28,12 +31,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Comparator; import java.util.Objects; +import java.util.TreeSet; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import libcore.io.IoUtils; - /** * Utility that rotates files over time, similar to {@code logrotate}. There is * a single "active" file, which is periodically rotated into historical files, @@ -302,17 +305,24 @@ public class FileRotator { public void readMatching(Reader reader, long matchStartMillis, long matchEndMillis) throws IOException { final FileInfo info = new FileInfo(mPrefix); + final TreeSet<Pair<Long, String>> readSet = new TreeSet<>( + Comparator.comparingLong(o -> o.first)); for (String name : mBasePath.list()) { if (!info.parse(name)) continue; - // read file when it overlaps + // Add file to set when it overlaps. if (info.startMillis <= matchEndMillis && matchStartMillis <= info.endMillis) { - if (LOGD) Log.d(TAG, "reading matching " + name); - - final File file = new File(mBasePath, name); - readFile(file, reader); + readSet.add(new Pair(info.startMillis, name)); } } + + // Read files in ascending order of start timestamp. + for (Pair<Long, String> pair : readSet) { + final String name = pair.second; + if (LOGD) Log.d(TAG, "reading matching " + name); + final File file = new File(mBasePath, name); + readFile(file, reader); + } } /** diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index bbaea0a45798..418000f60ca1 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -1806,15 +1806,10 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, if (!is_system_server && getuid() == 0) { const int rc = createProcessGroup(uid, getpid()); if (rc != 0) { - if (rc == -ESRCH) { - // If process is dead, treat this as a non-fatal error - ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc)); - } else { - fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing " - "CONFIG_CGROUP_CPUACCT?") - : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid, - /* pid= */ 0, strerror(-rc))); - } + fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing " + "CONFIG_CGROUP_CPUACCT?") + : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid, + /* pid= */ 0, strerror(-rc))); } } diff --git a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java index 952721320c90..73e47e1635b4 100644 --- a/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/FileRotatorTest.java @@ -366,6 +366,16 @@ public class FileRotatorTest extends AndroidTestCase { assertReadAll(rotate, "bar"); } + public void testReadSorted() throws Exception { + write("rotator.1024-2048", "2"); + write("rotator.2048-4096", "3"); + write("rotator.512-1024", "1"); + + final FileRotator rotate = new FileRotator( + mBasePath, PREFIX, SECOND_IN_MILLIS, SECOND_IN_MILLIS); + assertReadAll(rotate, "1", "2", "3"); + } + public void testFileSystemInaccessible() throws Exception { File inaccessibleDir = null; String dirPath = getContext().getFilesDir() + File.separator + "inaccessible"; @@ -422,16 +432,7 @@ public class FileRotatorTest extends AndroidTestCase { } public void assertRead(String... expected) { - assertEquals(expected.length, mActual.size()); - - final ArrayList<String> actualCopy = new ArrayList<String>(mActual); - for (String value : expected) { - if (!actualCopy.remove(value)) { - final String expectedString = Arrays.toString(expected); - final String actualString = Arrays.toString(mActual.toArray()); - fail("expected: " + expectedString + " but was: " + actualString); - } - } + assertEquals(Arrays.asList(expected), mActual); } } } diff --git a/data/keyboards/qwerty.idc b/data/keyboards/qwerty.idc deleted file mode 100644 index 375d78576548..000000000000 --- a/data/keyboards/qwerty.idc +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Emulator keyboard configuration file #1. -# - -touch.deviceType = touchScreen -touch.orientationAware = 1 - -keyboard.layout = qwerty -keyboard.characterMap = qwerty -keyboard.orientationAware = 1 -keyboard.builtIn = 1 - -cursor.mode = navigation -cursor.orientationAware = 1 diff --git a/data/keyboards/qwerty.kcm b/data/keyboards/qwerty.kcm deleted file mode 100644 index f3e152418a4c..000000000000 --- a/data/keyboards/qwerty.kcm +++ /dev/null @@ -1,508 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Emulator keyboard character map #1. -# -# This file is no longer used as the platform's default keyboard character map. -# Refer to Generic.kcm and Virtual.kcm instead. -# - -type ALPHA - -key A { - label: 'A' - number: '2' - base: 'a' - shift, capslock: 'A' - alt: '#' - shift+alt, capslock+alt: none -} - -key B { - label: 'B' - number: '2' - base: 'b' - shift, capslock: 'B' - alt: '<' - shift+alt, capslock+alt: none -} - -key C { - label: 'C' - number: '2' - base: 'c' - shift, capslock: 'C' - alt: '9' - shift+alt, capslock+alt: '\u00e7' -} - -key D { - label: 'D' - number: '3' - base: 'd' - shift, capslock: 'D' - alt: '5' - shift+alt, capslock+alt: none -} - -key E { - label: 'E' - number: '3' - base: 'e' - shift, capslock: 'E' - alt: '2' - shift+alt, capslock+alt: '\u0301' -} - -key F { - label: 'F' - number: '3' - base: 'f' - shift, capslock: 'F' - alt: '6' - shift+alt, capslock+alt: '\u00a5' -} - -key G { - label: 'G' - number: '4' - base: 'g' - shift, capslock: 'G' - alt: '-' - shift+alt, capslock+alt: '_' -} - -key H { - label: 'H' - number: '4' - base: 'h' - shift, capslock: 'H' - alt: '[' - shift+alt, capslock+alt: '{' -} - -key I { - label: 'I' - number: '4' - base: 'i' - shift, capslock: 'I' - alt: '$' - shift+alt, capslock+alt: '\u0302' -} - -key J { - label: 'J' - number: '5' - base: 'j' - shift, capslock: 'J' - alt: ']' - shift+alt, capslock+alt: '}' -} - -key K { - label: 'K' - number: '5' - base: 'k' - shift, capslock: 'K' - alt: '"' - shift+alt, capslock+alt: '~' -} - -key L { - label: 'L' - number: '5' - base: 'l' - shift, capslock: 'L' - alt: '\'' - shift+alt, capslock+alt: '`' -} - -key M { - label: 'M' - number: '6' - base: 'm' - shift, capslock: 'M' - alt: '!' - shift+alt, capslock+alt: none -} - -key N { - label: 'N' - number: '6' - base: 'n' - shift, capslock: 'N' - alt: '>' - shift+alt, capslock+alt: '\u0303' -} - -key O { - label: 'O' - number: '6' - base: 'o' - shift, capslock: 'O' - alt: '(' - shift+alt, capslock+alt: none -} - -key P { - label: 'P' - number: '7' - base: 'p' - shift, capslock: 'P' - alt: ')' - shift+alt, capslock+alt: none -} - -key Q { - label: 'Q' - number: '7' - base: 'q' - shift, capslock: 'Q' - alt: '*' - shift+alt, capslock+alt: '\u0300' -} - -key R { - label: 'R' - number: '7' - base: 'r' - shift, capslock: 'R' - alt: '3' - shift+alt, capslock+alt: '\u20ac' -} - -key S { - label: 'S' - number: '7' - base: 's' - shift, capslock: 'S' - alt: '4' - shift+alt, capslock+alt: '\u00df' -} - -key T { - label: 'T' - number: '8' - base: 't' - shift, capslock: 'T' - alt: '+' - shift+alt, capslock+alt: '\u00a3' -} - -key U { - label: 'U' - number: '8' - base: 'u' - shift, capslock: 'U' - alt: '&' - shift+alt, capslock+alt: '\u0308' -} - -key V { - label: 'V' - number: '8' - base: 'v' - shift, capslock: 'V' - alt: '=' - shift+alt, capslock+alt: '^' -} - -key W { - label: 'W' - number: '9' - base: 'w' - shift, capslock: 'W' - alt: '1' - shift+alt, capslock+alt: none -} - -key X { - label: 'X' - number: '9' - base: 'x' - shift, capslock: 'X' - alt: '8' - shift+alt, capslock+alt: '\uef00' -} - -key Y { - label: 'Y' - number: '9' - base: 'y' - shift, capslock: 'Y' - alt: '%' - shift+alt, capslock+alt: '\u00a1' -} - -key Z { - label: 'Z' - number: '9' - base: 'z' - shift, capslock: 'Z' - alt: '7' - shift+alt, capslock+alt: none -} - -key COMMA { - label: ',' - number: ',' - base: ',' - shift: ';' - alt: ';' - shift+alt: '|' -} - -key PERIOD { - label: '.' - number: '.' - base: '.' - shift: ':' - alt: ':' - shift+alt: '\u2026' -} - -key AT { - label: '@' - number: '0' - base: '@' - shift: '0' - alt: '0' - shift+alt: '\u2022' -} - -key SLASH { - label: '/' - number: '/' - base: '/' - shift: '?' - alt: '?' - shift+alt: '\\' -} - -key SPACE { - label: ' ' - number: ' ' - base: ' ' - shift: ' ' - alt: '\uef01' - shift+alt: '\uef01' -} - -key ENTER { - label: '\n' - number: '\n' - base: '\n' - shift: '\n' - alt: '\n' - shift+alt: '\n' -} - -key TAB { - label: '\t' - number: '\t' - base: '\t' - shift: '\t' - alt: '\t' - shift+alt: '\t' -} - -key 0 { - label: '0' - number: '0' - base: '0' - shift: ')' - alt: ')' - shift+alt: ')' -} - -key 1 { - label: '1' - number: '1' - base: '1' - shift: '!' - alt: '!' - shift+alt: '!' -} - -key 2 { - label: '2' - number: '2' - base: '2' - shift: '@' - alt: '@' - shift+alt: '@' -} - -key 3 { - label: '3' - number: '3' - base: '3' - shift: '#' - alt: '#' - shift+alt: '#' -} - -key 4 { - label: '4' - number: '4' - base: '4' - shift: '$' - alt: '$' - shift+alt: '$' -} - -key 5 { - label: '5' - number: '5' - base: '5' - shift: '%' - alt: '%' - shift+alt: '%' -} - -key 6 { - label: '6' - number: '6' - base: '6' - shift: '^' - alt: '^' - shift+alt: '^' -} - -key 7 { - label: '7' - number: '7' - base: '7' - shift: '&' - alt: '&' - shift+alt: '&' -} - -key 8 { - label: '8' - number: '8' - base: '8' - shift: '*' - alt: '*' - shift+alt: '*' -} - -key 9 { - label: '9' - number: '9' - base: '9' - shift: '(' - alt: '(' - shift+alt: '(' -} - -key GRAVE { - label: '`' - number: '`' - base: '`' - shift: '~' - alt: '`' - shift+alt: '~' -} - -key MINUS { - label: '-' - number: '-' - base: '-' - shift: '_' - alt: '-' - shift+alt: '_' -} - -key EQUALS { - label: '=' - number: '=' - base: '=' - shift: '+' - alt: '=' - shift+alt: '+' -} - -key LEFT_BRACKET { - label: '[' - number: '[' - base: '[' - shift: '{' - alt: '[' - shift+alt: '{' -} - -key RIGHT_BRACKET { - label: ']' - number: ']' - base: ']' - shift: '}' - alt: ']' - shift+alt: '}' -} - -key BACKSLASH { - label: '\\' - number: '\\' - base: '\\' - shift: '|' - alt: '\\' - shift+alt: '|' -} - -key SEMICOLON { - label: ';' - number: ';' - base: ';' - shift: ':' - alt: ';' - shift+alt: ':' -} - -key APOSTROPHE { - label: '\'' - number: '\'' - base: '\'' - shift: '"' - alt: '\'' - shift+alt: '"' -} - -key STAR { - label: '*' - number: '*' - base: '*' - shift: '*' - alt: '*' - shift+alt: '*' -} - -key POUND { - label: '#' - number: '#' - base: '#' - shift: '#' - alt: '#' - shift+alt: '#' -} - -key PLUS { - label: '+' - number: '+' - base: '+' - shift: '+' - alt: '+' - shift+alt: '+' -} diff --git a/data/keyboards/qwerty.kl b/data/keyboards/qwerty.kl deleted file mode 100644 index 2fd99abbb9fe..000000000000 --- a/data/keyboards/qwerty.kl +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Emulator keyboard layout #1. -# -# This file is no longer used as the platform's default keyboard layout. -# Refer to Generic.kl instead. -# - -key 399 GRAVE -key 2 1 -key 3 2 -key 4 3 -key 5 4 -key 6 5 -key 7 6 -key 8 7 -key 9 8 -key 10 9 -key 11 0 -key 158 BACK -key 230 SOFT_RIGHT -key 60 SOFT_LEFT -key 107 ENDCALL -key 62 ENDCALL -key 229 MENU -key 139 MENU -key 59 MENU -key 127 SEARCH -key 217 SEARCH -key 228 POUND -key 227 STAR -key 231 CALL -key 61 CALL -key 232 DPAD_CENTER -key 108 DPAD_DOWN -key 103 DPAD_UP -key 102 HOME -key 105 DPAD_LEFT -key 106 DPAD_RIGHT -key 115 VOLUME_UP -key 114 VOLUME_DOWN -key 116 POWER -key 212 CAMERA - -key 16 Q -key 17 W -key 18 E -key 19 R -key 20 T -key 21 Y -key 22 U -key 23 I -key 24 O -key 25 P -key 26 LEFT_BRACKET -key 27 RIGHT_BRACKET -key 43 BACKSLASH - -key 30 A -key 31 S -key 32 D -key 33 F -key 34 G -key 35 H -key 36 J -key 37 K -key 38 L -key 39 SEMICOLON -key 40 APOSTROPHE -key 14 DEL - -key 44 Z -key 45 X -key 46 C -key 47 V -key 48 B -key 49 N -key 50 M -key 51 COMMA -key 52 PERIOD -key 53 SLASH -key 28 ENTER - -key 56 ALT_LEFT -key 100 ALT_RIGHT -key 42 SHIFT_LEFT -key 54 SHIFT_RIGHT -key 15 TAB -key 57 SPACE -key 150 EXPLORER -key 155 ENVELOPE - -key 12 MINUS -key 13 EQUALS -key 215 AT - -# On an AT keyboard: ESC, F10 -key 1 BACK -key 68 MENU - -# App switch = Overview key -key 580 APP_SWITCH - -# Media control keys -key 160 MEDIA_CLOSE -key 161 MEDIA_EJECT -key 163 MEDIA_NEXT -key 164 MEDIA_PLAY_PAUSE -key 165 MEDIA_PREVIOUS -key 166 MEDIA_STOP -key 167 MEDIA_RECORD -key 168 MEDIA_REWIND - -key 142 SLEEP -key 581 STEM_PRIMARY -key 582 STEM_1 -key 583 STEM_2 -key 584 STEM_3 diff --git a/data/keyboards/qwerty2.idc b/data/keyboards/qwerty2.idc deleted file mode 100644 index 369205ea3f98..000000000000 --- a/data/keyboards/qwerty2.idc +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Emulator keyboard configuration file #2. -# - -touch.deviceType = touchScreen -touch.orientationAware = 1 - -keyboard.layout = qwerty -keyboard.characterMap = qwerty2 -keyboard.orientationAware = 1 -keyboard.builtIn = 1 - -cursor.mode = navigation -cursor.orientationAware = 1 diff --git a/data/keyboards/qwerty2.kcm b/data/keyboards/qwerty2.kcm deleted file mode 100644 index b981d835bdfb..000000000000 --- a/data/keyboards/qwerty2.kcm +++ /dev/null @@ -1,505 +0,0 @@ -# Copyright (C) 2010 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. - -# -# Emulator keyboard character map #2. -# - -type ALPHA - -key A { - label: 'A' - number: '2' - base: 'a' - shift, capslock: 'A' - alt: '\u00e1' - shift+alt, capslock+alt: '\u00c1' -} - -key B { - label: 'B' - number: '2' - base: 'b' - shift, capslock: 'B' - alt: 'b' - shift+alt, capslock+alt: 'B' -} - -key C { - label: 'C' - number: '2' - base: 'c' - shift, capslock: 'C' - alt: '\u00a9' - shift+alt, capslock+alt: '\u00a2' -} - -key D { - label: 'D' - number: '3' - base: 'd' - shift, capslock: 'D' - alt: '\u00f0' - shift+alt, capslock+alt: '\u00d0' -} - -key E { - label: 'E' - number: '3' - base: 'e' - shift, capslock: 'E' - alt: '\u00e9' - shift+alt, capslock+alt: '\u00c9' -} - -key F { - label: 'F' - number: '3' - base: 'f' - shift, capslock: 'F' - alt: '[' - shift+alt, capslock+alt: '[' -} - -key G { - label: 'G' - number: '4' - base: 'g' - shift, capslock: 'G' - alt: ']' - shift+alt, capslock+alt: ']' -} - -key H { - label: 'H' - number: '4' - base: 'h' - shift, capslock: 'H' - alt: '<' - shift+alt, capslock+alt: '<' -} - -key I { - label: 'I' - number: '4' - base: 'i' - shift, capslock: 'I' - alt: '\u00ed' - shift+alt, capslock+alt: '\u00cd' -} - -key J { - label: 'J' - number: '5' - base: 'j' - shift, capslock: 'J' - alt: '>' - shift+alt, capslock+alt: '>' -} - -key K { - label: 'K' - number: '5' - base: 'k' - shift, capslock: 'K' - alt: ';' - shift+alt, capslock+alt: '~' -} - -key L { - label: 'L' - number: '5' - base: 'l' - shift, capslock: 'L' - alt: '\u00f8' - shift+alt, capslock+alt: '\u00d8' -} - -key M { - label: 'M' - number: '6' - base: 'm' - shift, capslock: 'M' - alt: '\u00b5' - shift+alt, capslock+alt: none -} - -key N { - label: 'N' - number: '6' - base: 'n' - shift, capslock: 'N' - alt: '\u00f1' - shift+alt, capslock+alt: '\u00d1' -} - -key O { - label: 'O' - number: '6' - base: 'o' - shift, capslock: 'O' - alt: '\u00f3' - shift+alt, capslock+alt: '\u00d3' -} - -key P { - label: 'P' - number: '7' - base: 'p' - shift, capslock: 'P' - alt: '\u00f6' - shift+alt, capslock+alt: '\u00d6' -} - -key Q { - label: 'Q' - number: '7' - base: 'q' - shift, capslock: 'Q' - alt: '\u00e4' - shift+alt, capslock+alt: '\u00c4' -} - -key R { - label: 'R' - number: '7' - base: 'r' - shift, capslock: 'R' - alt: '\u00ae' - shift+alt, capslock+alt: 'R' -} - -key S { - label: 'S' - number: '7' - base: 's' - shift, capslock: 'S' - alt: '\u00df' - shift+alt, capslock+alt: '\u00a7' -} - -key T { - label: 'T' - number: '8' - base: 't' - shift, capslock: 'T' - alt: '\u00fe' - shift+alt, capslock+alt: '\u00de' -} - -key U { - label: 'U' - number: '8' - base: 'u' - shift, capslock: 'U' - alt: '\u00fa' - shift+alt, capslock+alt: '\u00da' -} - -key V { - label: 'V' - number: '8' - base: 'v' - shift, capslock: 'V' - alt: 'v' - shift+alt, capslock+alt: 'V' -} - -key W { - label: 'W' - number: '9' - base: 'w' - shift, capslock: 'W' - alt: '\u00e5' - shift+alt, capslock+alt: '\u00c5' -} - -key X { - label: 'X' - number: '9' - base: 'x' - shift, capslock: 'X' - alt: 'x' - shift+alt, capslock+alt: '\uef00' -} - -key Y { - label: 'Y' - number: '9' - base: 'y' - shift, capslock: 'Y' - alt: '\u00fc' - shift+alt, capslock+alt: '\u00dc' -} - -key Z { - label: 'Z' - number: '9' - base: 'z' - shift, capslock: 'Z' - alt: '\u00e6' - shift+alt, capslock+alt: '\u00c6' -} - -key COMMA { - label: ',' - number: ',' - base: ',' - shift: '<' - alt: '\u00e7' - shift+alt: '\u00c7' -} - -key PERIOD { - label: '.' - number: '.' - base: '.' - shift: '>' - alt: '.' - shift+alt: '\u2026' -} - -key AT { - label: '@' - number: '@' - base: '@' - shift: '@' - alt: '@' - shift+alt: '\u2022' -} - -key SLASH { - label: '/' - number: '/' - base: '/' - shift: '?' - alt: '\u00bf' - shift+alt: '?' -} - -key SPACE { - label: ' ' - number: ' ' - base: ' ' - shift: ' ' - alt: '\uef01' - shift+alt: '\uef01' -} - -key ENTER { - label: '\n' - number: '\n' - base: '\n' - shift: '\n' - alt: '\n' - shift+alt: '\n' -} - -key TAB { - label: '\t' - number: '\t' - base: '\t' - shift: '\t' - alt: '\t' - shift+alt: '\t' -} - -key 0 { - label: '0' - number: '0' - base: '0' - shift: ')' - alt: '\u02bc' - shift+alt: ')' -} - -key 1 { - label: '1' - number: '1' - base: '1' - shift: '!' - alt: '\u00a1' - shift+alt: '\u00b9' -} - -key 2 { - label: '2' - number: '2' - base: '2' - shift: '@' - alt: '\u00b2' - shift+alt: '@' -} - -key 3 { - label: '3' - number: '3' - base: '3' - shift: '#' - alt: '\u00b3' - shift+alt: '#' -} - -key 4 { - label: '4' - number: '4' - base: '4' - shift: '$' - alt: '\u00a4' - shift+alt: '\u00a3' -} - -key 5 { - label: '5' - number: '5' - base: '5' - shift: '%' - alt: '\u20ac' - shift+alt: '%' -} - -key 6 { - label: '6' - number: '6' - base: '6' - shift: '^' - alt: '\u00bc' - shift+alt: '\u0302' -} - -key 7 { - label: '7' - number: '7' - base: '7' - shift: '&' - alt: '\u00bd' - shift+alt: '&' -} - -key 8 { - label: '8' - number: '8' - base: '8' - shift: '*' - alt: '\u00be' - shift+alt: '*' -} - -key 9 { - label: '9' - number: '9' - base: '9' - shift: '(' - alt: '\u02bb' - shift+alt: '(' -} - -key GRAVE { - label: '`' - number: '`' - base: '`' - shift: '~' - alt: '\u0300' - shift+alt: '\u0303' -} - -key MINUS { - label: '-' - number: '-' - base: '-' - shift: '_' - alt: '\u00a5' - shift+alt: '_' -} - -key EQUALS { - label: '=' - number: '=' - base: '=' - shift: '+' - alt: '\u00d7' - shift+alt: '\u00f7' -} - -key LEFT_BRACKET { - label: '[' - number: '[' - base: '[' - shift: '{' - alt: '\u00ab' - shift+alt: '{' -} - -key RIGHT_BRACKET { - label: ']' - number: ']' - base: ']' - shift: '}' - alt: '\u00bb' - shift+alt: '}' -} - -key BACKSLASH { - label: '\\' - number: '\\' - base: '\\' - shift: '|' - alt: '\u00ac' - shift+alt: '\u00a6' -} - -key SEMICOLON { - label: ';' - number: ';' - base: ';' - shift: ':' - alt: '\u00b6' - shift+alt: '\u00b0' -} - -key APOSTROPHE { - label: '\'' - number: '\'' - base: '\'' - shift: '"' - alt: '\u0301' - shift+alt: '\u0308' -} - -key STAR { - label: '*' - number: '*' - base: '*' - shift: '*' - alt: '*' - shift+alt: '*' -} - -key POUND { - label: '#' - number: '#' - base: '#' - shift: '#' - alt: '#' - shift+alt: '#' -} - -key PLUS { - label: '+' - number: '+' - base: '+' - shift: '+' - alt: '+' - shift+alt: '+' -} diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index fd6e18ee364a..68befffecf2f 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -812,10 +812,10 @@ Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode m /* check the appropriate Zip file */ ZipFileRO* pZip = getZipFileLocked(ap); if (pZip != NULL) { - ALOGV("GOT zip, checking NA '%s'", (const char*) path); + ALOGV("GOT zip, checking NA '%s'", path.c_str()); ZipEntryRO entry = pZip->findEntryByName(path.c_str()); if (entry != NULL) { - ALOGV("FOUND NA in Zip file for %s", (const char*) path); + ALOGV("FOUND NA in Zip file for %s", path.c_str()); pAsset = openAssetFromZipLocked(pZip, entry, mode, path); pZip->releaseEntry(entry); } @@ -1425,7 +1425,7 @@ AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen) mResourceTableAsset(NULL), mResourceTable(NULL) { if (kIsDebug) { - ALOGI("Creating SharedZip %p %s\n", this, (const char*)mPath); + ALOGI("Creating SharedZip %p %s\n", this, mPath.c_str()); } ALOGV("+++ opening zip '%s'\n", mPath.c_str()); mZipFile = ZipFileRO::open(mPath.c_str()); @@ -1439,7 +1439,7 @@ AssetManager::SharedZip::SharedZip(int fd, const String8& path) mResourceTableAsset(NULL), mResourceTable(NULL) { if (kIsDebug) { - ALOGI("Creating SharedZip %p fd=%d %s\n", this, fd, (const char*)mPath); + ALOGI("Creating SharedZip %p fd=%d %s\n", this, fd, mPath.c_str()); } ALOGV("+++ opening zip fd=%d '%s'\n", fd, mPath.c_str()); mZipFile = ZipFileRO::openFd(fd, mPath.c_str()); @@ -1453,7 +1453,7 @@ sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path, bool createIfNotPresent) { AutoMutex _l(gLock); - time_t modWhen = getFileModDate(path); + time_t modWhen = getFileModDate(path.c_str()); sp<SharedZip> zip = gOpen.valueFor(path).promote(); if (zip != NULL && zip->mModWhen == modWhen) { return zip; @@ -1541,7 +1541,7 @@ bool AssetManager::SharedZip::getOverlay(size_t idx, asset_path* out) const AssetManager::SharedZip::~SharedZip() { if (kIsDebug) { - ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath); + ALOGI("Destroying SharedZip %p %s\n", this, mPath.c_str()); } if (mResourceTable != NULL) { delete mResourceTable; diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index fc9dd145dc5d..daed277c7314 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -99,6 +99,13 @@ struct FindEntryResult { StringPoolRef entry_string_ref; }; +struct Theme::Entry { + uint32_t attr_res_id; + ApkAssetsCookie cookie; + uint32_t type_spec_flags; + Res_value value; +}; + AssetManager2::AssetManager2() { memset(&configuration_, 0, sizeof(configuration_)); } @@ -897,7 +904,7 @@ std::string AssetManager2::GetLastResourceResolution() const { log_stream << "\nBest matching is from " << (last_resolution_.best_config_name.empty() ? "default" - : last_resolution_.best_config_name) + : last_resolution_.best_config_name.c_str()) << " configuration of " << last_resolution_.best_package_name; return log_stream.str(); } @@ -1411,13 +1418,6 @@ Theme::Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) { Theme::~Theme() = default; -struct Theme::Entry { - uint32_t attr_res_id; - ApkAssetsCookie cookie; - uint32_t type_spec_flags; - Res_value value; -}; - namespace { struct ThemeEntryKeyComparer { bool operator() (const Theme::Entry& entry, uint32_t attr_res_id) const noexcept { diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index cc380625d9be..11d153eb0d14 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -5214,19 +5214,19 @@ bool ResTable::expandResourceRef(const char16_t* refStr, size_t refLen, *outType = *defType; } *outName = String16(p, end-p); - if(**outPackage == 0) { + if(outPackage->empty()) { if(outErrorMsg) { *outErrorMsg = "Resource package cannot be an empty string"; } return false; } - if(**outType == 0) { + if(outType->empty()) { if(outErrorMsg) { *outErrorMsg = "Resource type cannot be an empty string"; } return false; } - if(**outName == 0) { + if(outName->empty()) { if(outErrorMsg) { *outErrorMsg = "Resource id cannot be an empty string"; } diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h index f4a358de1c41..1bfb874729d7 100644 --- a/libs/protoutil/include/android/util/ProtoOutputStream.h +++ b/libs/protoutil/include/android/util/ProtoOutputStream.h @@ -102,7 +102,7 @@ public: bool write(uint64_t fieldId, long val); bool write(uint64_t fieldId, long long val); bool write(uint64_t fieldId, bool val); - bool write(uint64_t fieldId, std::string val); + bool write(uint64_t fieldId, std::string_view val); bool write(uint64_t fieldId, const char* val, size_t size); /** diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp index fcf82eed4eb1..a44a1b210924 100644 --- a/libs/protoutil/src/ProtoOutputStream.cpp +++ b/libs/protoutil/src/ProtoOutputStream.cpp @@ -170,13 +170,13 @@ ProtoOutputStream::write(uint64_t fieldId, bool val) } bool -ProtoOutputStream::write(uint64_t fieldId, std::string val) +ProtoOutputStream::write(uint64_t fieldId, std::string_view val) { if (mCompact) return false; const uint32_t id = (uint32_t)fieldId; switch (fieldId & FIELD_TYPE_MASK) { case FIELD_TYPE_STRING: - writeUtf8StringImpl(id, val.c_str(), val.size()); + writeUtf8StringImpl(id, val.data(), val.size()); return true; default: ALOGW("Field type %" PRIu64 " is not supported when writing string val.", diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index b8090c4e1688..1100c545b89f 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -1240,7 +1240,8 @@ public final class AudioFormat implements Parcelable { * {@link AudioFormat#CHANNEL_OUT_SIDE_RIGHT}. * <p> For a valid {@link AudioTrack} channel position mask, * the following conditions apply: - * <br> (1) at most eight channel positions may be used; + * <br> (1) at most {@link AudioSystem#OUT_CHANNEL_COUNT_MAX} channel positions may be + * used; * <br> (2) right/left pairs should be matched. * <p> For input or {@link AudioRecord}, the mask should be * {@link AudioFormat#CHANNEL_IN_MONO} or diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 44a0baa5faa7..27fc6ae71ed2 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -1040,7 +1040,7 @@ static jthrowable createCodecException( CHECK(ctor != NULL); ScopedLocalRef<jstring> msgObj( - env, env->NewStringUTF(msg != NULL ? msg : String8::format("Error %#x", err))); + env, env->NewStringUTF(msg != NULL ? msg : String8::format("Error %#x", err).c_str())); // translate action code to Java equivalent switch (actionCode) { @@ -2912,7 +2912,7 @@ static void android_media_MediaCodec_setVideoScalingMode( if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) { jniThrowException(env, "java/lang/IllegalArgumentException", - String8::format("Unrecognized mode: %d", mode)); + String8::format("Unrecognized mode: %d", mode).c_str()); return; } @@ -3337,27 +3337,27 @@ static void android_media_MediaCodec_native_setup( if (err == NAME_NOT_FOUND) { // fail and do not try again. jniThrowException(env, "java/lang/IllegalArgumentException", - String8::format("Failed to initialize %s, error %#x (NAME_NOT_FOUND)", tmp, err)); + String8::format("Failed to initialize %s, error %#x (NAME_NOT_FOUND)", tmp, err).c_str()); env->ReleaseStringUTFChars(name, tmp); return; } if (err == NO_MEMORY) { throwCodecException(env, err, ACTION_CODE_TRANSIENT, - String8::format("Failed to initialize %s, error %#x (NO_MEMORY)", tmp, err)); + String8::format("Failed to initialize %s, error %#x (NO_MEMORY)", tmp, err).c_str()); env->ReleaseStringUTFChars(name, tmp); return; } if (err == PERMISSION_DENIED) { jniThrowException(env, "java/lang/SecurityException", String8::format("Failed to initialize %s, error %#x (PERMISSION_DENIED)", tmp, - err)); + err).c_str()); env->ReleaseStringUTFChars(name, tmp); return; } if (err != OK) { // believed possible to try again jniThrowException(env, "java/io/IOException", - String8::format("Failed to find matching codec %s, error %#x (?)", tmp, err)); + String8::format("Failed to find matching codec %s, error %#x (?)", tmp, err).c_str()); env->ReleaseStringUTFChars(name, tmp); return; } diff --git a/media/jni/android_media_MediaDescrambler.cpp b/media/jni/android_media_MediaDescrambler.cpp index c61365a448d3..37111c28c242 100644 --- a/media/jni/android_media_MediaDescrambler.cpp +++ b/media/jni/android_media_MediaDescrambler.cpp @@ -368,7 +368,7 @@ static jthrowable createServiceSpecificException( ScopedLocalRef<jstring> msgObj( env, env->NewStringUTF(msg != NULL ? - msg : String8::format("Error %#x", serviceSpecificError))); + msg : String8::format("Error %#x", serviceSpecificError).c_str())); return (jthrowable)env->NewObject( clazz.get(), ctor, serviceSpecificError, msgObj.get()); diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 43de37850b89..febaba9303af 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -260,7 +260,7 @@ android_media_MediaPlayer_setDataSourceAndHeaders( status_t opStatus = mp->setDataSource( httpService, - pathStr, + pathStr.c_str(), headersVector.size() > 0? &headersVector : NULL); process_media_player_call( diff --git a/native/android/obb.cpp b/native/android/obb.cpp index e9900249b289..a14fa7e58fa8 100644 --- a/native/android/obb.cpp +++ b/native/android/obb.cpp @@ -42,7 +42,7 @@ void AObbInfo_delete(AObbInfo* obbInfo) { } const char* AObbInfo_getPackageName(AObbInfo* obbInfo) { - return obbInfo->getPackageName(); + return obbInfo->getPackageName().c_str(); } int32_t AObbInfo_getVersion(AObbInfo* obbInfo) { diff --git a/packages/CredentialManager/horologist/OWNERS b/packages/CredentialManager/horologist/OWNERS new file mode 100644 index 000000000000..b67932835b4a --- /dev/null +++ b/packages/CredentialManager/horologist/OWNERS @@ -0,0 +1,4 @@ +include /core/java/android/credentials/OWNERS + +shuanghao@google.com +gustavopagani@google.com diff --git a/packages/CredentialManager/shared/OWNERS b/packages/CredentialManager/shared/OWNERS new file mode 100644 index 000000000000..b67932835b4a --- /dev/null +++ b/packages/CredentialManager/shared/OWNERS @@ -0,0 +1,4 @@ +include /core/java/android/credentials/OWNERS + +shuanghao@google.com +gustavopagani@google.com diff --git a/packages/CredentialManager/wear/OWNERS b/packages/CredentialManager/wear/OWNERS new file mode 100644 index 000000000000..b67932835b4a --- /dev/null +++ b/packages/CredentialManager/wear/OWNERS @@ -0,0 +1,4 @@ +include /core/java/android/credentials/OWNERS + +shuanghao@google.com +gustavopagani@google.com diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 0cd8b455cc03..5b2409abc113 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -6,6 +6,7 @@ dsandler@android.com aaliomer@google.com aaronjli@google.com +achalke@google.com acul@google.com adamcohen@google.com aioana@google.com @@ -72,6 +73,7 @@ omarmt@google.com patmanning@google.com peanutbutter@google.com peskal@google.com +petrcermak@google.com pinyaoting@google.com pixel@google.com pomini@google.com @@ -83,14 +85,17 @@ santie@google.com shanh@google.com snoeberger@google.com steell@google.com +stevenckng@google.com stwu@google.com syeonlee@google.com sunnygoyal@google.com thiruram@google.com +tkachenkoi@google.com tracyzhou@google.com tsuji@google.com twickham@google.com vadimt@google.com +vanjan@google.com victortulias@google.com winsonc@google.com wleshner@google.com diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index a08f540bb1b1..6507488c73f5 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -549,6 +549,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab dispatchErrorMessage(message); } + @Override + public void onEnabledTrustAgentsChanged(int userId) { + Assert.isMainThread(); + + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onEnabledTrustAgentsChanged(userId); + } + } + } + private void handleSimSubscriptionInfoChanged() { Assert.isMainThread(); mLogger.v("onSubscriptionInfoChanged()"); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index feff216310df..73940055c89f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -322,4 +322,9 @@ public class KeyguardUpdateMonitorCallback { * Called when keyguard is going away or not going away. */ public void onKeyguardGoingAway() { } + + /** + * Called when the enabled trust agents associated with the specified user. + */ + public void onEnabledTrustAgentsChanged(int userId) { } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt index d90f328719bb..e912053a85ca 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt @@ -75,6 +75,8 @@ constructor( override fun onTrustError(message: CharSequence?) = Unit override fun onTrustManagedChanged(enabled: Boolean, userId: Int) = Unit + + override fun onEnabledTrustAgentsChanged(userId: Int) = Unit } trustManager.registerTrustListener(callback) logger.trustListenerRegistered() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java index f1269f2b012a..f4cf4eff8a7a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -452,5 +452,10 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum public void onBiometricsCleared() { update(false /* alwaysUpdate */); } + + @Override + public void onEnabledTrustAgentsChanged(int userId) { + update(false /* updateAlways */); + } } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index b1051af4ad15..417eb40eab54 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -144,6 +144,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; +import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; @@ -722,6 +723,18 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void testOnEnabledTrustAgentsChangedCallback() { + final Random random = new Random(); + final int userId = random.nextInt(); + final KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class); + + mKeyguardUpdateMonitor.registerCallback(callback); + mKeyguardUpdateMonitor.onEnabledTrustAgentsChanged(userId); + + verify(callback).onEnabledTrustAgentsChanged(eq(userId)); + } + + @Test public void trustAgentHasTrust_fingerprintLockout() { // GIVEN user has trust mKeyguardUpdateMonitor.onTrustChanged(true, true, getCurrentUser(), 0, null); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java index 8f363efd9f51..d787ada90a73 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java @@ -31,18 +31,23 @@ import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import dagger.Lazy; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import dagger.Lazy; +import java.util.Random; + @SmallTest @TestableLooper.RunWithLooper @@ -169,4 +174,19 @@ public class KeyguardStateControllerTest extends SysuiTestCase { verify(callback).onKeyguardDismissAmountChanged(); } + @Test + public void testOnEnabledTrustAgentsChangedCallback() { + final Random random = new Random(); + final ArgumentCaptor<KeyguardUpdateMonitorCallback> updateCallbackCaptor = + ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class); + + verify(mKeyguardUpdateMonitor).registerCallback(updateCallbackCaptor.capture()); + final KeyguardStateController.Callback stateCallback = + mock(KeyguardStateController.Callback.class); + mKeyguardStateController.addCallback(stateCallback); + + when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); + updateCallbackCaptor.getValue().onEnabledTrustAgentsChanged(random.nextInt()); + verify(stateCallback).onUnlockedChanged(); + } } diff --git a/services/backup/backuplib/java/com/android/server/backup/TransportManager.java b/services/backup/backuplib/java/com/android/server/backup/TransportManager.java index 930f49e4d117..ff5f509fb11b 100644 --- a/services/backup/backuplib/java/com/android/server/backup/TransportManager.java +++ b/services/backup/backuplib/java/com/android/server/backup/TransportManager.java @@ -706,6 +706,9 @@ public class TransportManager { try { String transportName = transport.name(); String transportDirName = transport.transportDirName(); + if (transportName == null || transportDirName == null) { + return BackupManager.ERROR_TRANSPORT_INVALID; + } registerTransport(transportComponent, transport); // If registerTransport() hasn't thrown... Slog.d(TAG, "Transport " + transportString + " registered"); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index 846c2d9f3df7..a53d09678cd3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -433,6 +433,11 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } @Override + public void onEnabledTrustAgentsChanged(int userId) { + + } + + @Override @NonNull public List<FingerprintSensorPropertiesInternal> getSensorProperties() { final List<FingerprintSensorPropertiesInternal> properties = new ArrayList<>(); diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 04cd7f72acc9..e3abf0c43397 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -53,6 +53,7 @@ import android.os.Bundle; import android.os.DeadObjectException; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; import android.os.RemoteException; @@ -150,6 +151,8 @@ public class TrustManagerService extends SystemService { private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>(); private final Receiver mReceiver = new Receiver(); + private final Handler mHandler; + /* package */ final TrustArchive mArchive = new TrustArchive(); private final Context mContext; private final LockPatternUtils mLockPatternUtils; @@ -158,10 +161,26 @@ public class TrustManagerService extends SystemService { private VirtualDeviceManagerInternal mVirtualDeviceManager; private enum TrustState { - UNTRUSTED, // the phone is not unlocked by any trustagents - TRUSTABLE, // the phone is in a semi-locked state that can be unlocked if - // FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE is passed and a trustagent is trusted - TRUSTED // the phone is unlocked + // UNTRUSTED means that TrustManagerService is currently *not* giving permission for the + // user's Keyguard to be dismissed, and grants of trust by trust agents are remembered in + // the corresponding TrustAgentWrapper but are not recognized until the device is unlocked + // for the user. I.e., if the device is locked and the state is UNTRUSTED, it cannot be + // unlocked by a trust agent. Automotive devices are an exception; grants of trust are + // always recognized on them. + UNTRUSTED, + + // TRUSTABLE is the same as UNTRUSTED except that new grants of trust using + // FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE are recognized for moving to TRUSTED. I.e., if + // the device is locked and the state is TRUSTABLE, it can be unlocked by a trust agent, + // provided that the trust agent chooses to use Active Unlock. The TRUSTABLE state is only + // possible as a result of a downgrade from TRUSTED, after a trust agent used + // FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE in its most recent grant. + TRUSTABLE, + + // TRUSTED means that TrustManagerService is currently giving permission for the user's + // Keyguard to be dismissed. This implies that the device is unlocked for the user (where + // the case of Keyguard showing but dismissible just with swipe counts as "unlocked"). + TRUSTED }; @GuardedBy("mUserTrustState") @@ -224,13 +243,40 @@ public class TrustManagerService extends SystemService { private boolean mTrustAgentsCanRun = false; private int mCurrentUser = UserHandle.USER_SYSTEM; + /** + * A class for providing dependencies to {@link TrustManagerService} in both production and test + * cases. + */ + protected static class Injector { + private final LockPatternUtils mLockPatternUtils; + private final Looper mLooper; + + public Injector(LockPatternUtils lockPatternUtils, Looper looper) { + mLockPatternUtils = lockPatternUtils; + mLooper = looper; + } + + LockPatternUtils getLockPatternUtils() { + return mLockPatternUtils; + } + + Looper getLooper() { + return mLooper; + } + } + public TrustManagerService(Context context) { + this(context, new Injector(new LockPatternUtils(context), Looper.myLooper())); + } + + protected TrustManagerService(Context context, Injector injector) { super(context); mContext = context; + mHandler = createHandler(injector.getLooper()); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - mLockPatternUtils = new LockPatternUtils(context); - mStrongAuthTracker = new StrongAuthTracker(context); + mLockPatternUtils = injector.getLockPatternUtils(); + mStrongAuthTracker = new StrongAuthTracker(context, injector.getLooper()); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mSettingsObserver = new SettingsObserver(mHandler); } @@ -814,6 +860,12 @@ public class TrustManagerService extends SystemService { } } + private TrustState getUserTrustStateInner(int userId) { + synchronized (mUserTrustState) { + return mUserTrustState.get(userId, TrustState.UNTRUSTED); + } + } + boolean isDeviceLockedInner(int userId) { synchronized (mDeviceLockedForUser) { return mDeviceLockedForUser.get(userId, true); @@ -864,7 +916,12 @@ public class TrustManagerService extends SystemService { continue; } - boolean trusted = aggregateIsTrusted(id); + final boolean trusted; + if (android.security.Flags.fixUnlockedDeviceRequiredKeys()) { + trusted = getUserTrustStateInner(id) == TrustState.TRUSTED; + } else { + trusted = aggregateIsTrusted(id); + } boolean showingKeyguard = true; boolean biometricAuthenticated = false; boolean currentUserIsUnlocked = false; @@ -1365,6 +1422,23 @@ public class TrustManagerService extends SystemService { } } + private void dispatchOnEnabledTrustAgentsChanged(int userId) { + if (DEBUG) { + Log.i(TAG, "onEnabledTrustAgentsChanged(" + userId + ")"); + } + for (int i = 0; i < mTrustListeners.size(); i++) { + try { + mTrustListeners.get(i).onEnabledTrustAgentsChanged(userId); + } catch (DeadObjectException e) { + Slog.d(TAG, "Removing dead TrustListener."); + mTrustListeners.remove(i); + i--; + } catch (RemoteException e) { + Slog.e(TAG, "Exception while notifying TrustListener.", e); + } + } + } + private void dispatchOnTrustManagedChanged(boolean managed, int userId) { if (DEBUG) { Log.i(TAG, "onTrustManagedChanged(" + managed + ", " + userId + ")"); @@ -1468,9 +1542,7 @@ public class TrustManagerService extends SystemService { @Override public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException { enforceReportPermission(); - // coalesce refresh messages. - mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED); - mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED); + mHandler.obtainMessage(MSG_ENABLED_AGENTS_CHANGED, userId, 0).sendToTarget(); } @Override @@ -1628,7 +1700,7 @@ public class TrustManagerService extends SystemService { if (isCurrent) { fout.print(" (current)"); } - fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id))); + fout.print(": trustState=" + getUserTrustStateInner(user.id)); fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id))); fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id))); fout.print(", strongAuthRequired=" + dumpHex( @@ -1781,88 +1853,91 @@ public class TrustManagerService extends SystemService { } } - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_REGISTER_LISTENER: - addListener((ITrustListener) msg.obj); - break; - case MSG_UNREGISTER_LISTENER: - removeListener((ITrustListener) msg.obj); - break; - case MSG_DISPATCH_UNLOCK_ATTEMPT: - dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2); - break; - case MSG_USER_REQUESTED_UNLOCK: - dispatchUserRequestedUnlock(msg.arg1, msg.arg2 != 0); - break; - case MSG_USER_MAY_REQUEST_UNLOCK: - dispatchUserMayRequestUnlock(msg.arg1); - break; - case MSG_DISPATCH_UNLOCK_LOCKOUT: - dispatchUnlockLockout(msg.arg1, msg.arg2); - break; - case MSG_ENABLED_AGENTS_CHANGED: - refreshAgentList(UserHandle.USER_ALL); - // This is also called when the security mode of a user changes. - refreshDeviceLockedForUser(UserHandle.USER_ALL); - break; - case MSG_KEYGUARD_SHOWING_CHANGED: - dispatchTrustableDowngrade(); - refreshDeviceLockedForUser(mCurrentUser); - break; - case MSG_START_USER: - case MSG_CLEANUP_USER: - case MSG_UNLOCK_USER: - refreshAgentList(msg.arg1); - break; - case MSG_SWITCH_USER: - mCurrentUser = msg.arg1; - mSettingsObserver.updateContentObserver(); - refreshDeviceLockedForUser(UserHandle.USER_ALL); - break; - case MSG_STOP_USER: - setDeviceLockedForUser(msg.arg1, true); - break; - case MSG_FLUSH_TRUST_USUALLY_MANAGED: - SparseBooleanArray usuallyManaged; - synchronized (mTrustUsuallyManagedForUser) { - usuallyManaged = mTrustUsuallyManagedForUser.clone(); - } + private Handler createHandler(Looper looper) { + return new Handler(looper) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_REGISTER_LISTENER: + addListener((ITrustListener) msg.obj); + break; + case MSG_UNREGISTER_LISTENER: + removeListener((ITrustListener) msg.obj); + break; + case MSG_DISPATCH_UNLOCK_ATTEMPT: + dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2); + break; + case MSG_USER_REQUESTED_UNLOCK: + dispatchUserRequestedUnlock(msg.arg1, msg.arg2 != 0); + break; + case MSG_USER_MAY_REQUEST_UNLOCK: + dispatchUserMayRequestUnlock(msg.arg1); + break; + case MSG_DISPATCH_UNLOCK_LOCKOUT: + dispatchUnlockLockout(msg.arg1, msg.arg2); + break; + case MSG_ENABLED_AGENTS_CHANGED: + refreshAgentList(UserHandle.USER_ALL); + // This is also called when the security mode of a user changes. + refreshDeviceLockedForUser(UserHandle.USER_ALL); + dispatchOnEnabledTrustAgentsChanged(msg.arg1); + break; + case MSG_KEYGUARD_SHOWING_CHANGED: + dispatchTrustableDowngrade(); + refreshDeviceLockedForUser(mCurrentUser); + break; + case MSG_START_USER: + case MSG_CLEANUP_USER: + case MSG_UNLOCK_USER: + refreshAgentList(msg.arg1); + break; + case MSG_SWITCH_USER: + mCurrentUser = msg.arg1; + mSettingsObserver.updateContentObserver(); + refreshDeviceLockedForUser(UserHandle.USER_ALL); + break; + case MSG_STOP_USER: + setDeviceLockedForUser(msg.arg1, true); + break; + case MSG_FLUSH_TRUST_USUALLY_MANAGED: + SparseBooleanArray usuallyManaged; + synchronized (mTrustUsuallyManagedForUser) { + usuallyManaged = mTrustUsuallyManagedForUser.clone(); + } - for (int i = 0; i < usuallyManaged.size(); i++) { - int userId = usuallyManaged.keyAt(i); - boolean value = usuallyManaged.valueAt(i); - if (value != mLockPatternUtils.isTrustUsuallyManaged(userId)) { - mLockPatternUtils.setTrustUsuallyManaged(value, userId); + for (int i = 0; i < usuallyManaged.size(); i++) { + int userId = usuallyManaged.keyAt(i); + boolean value = usuallyManaged.valueAt(i); + if (value != mLockPatternUtils.isTrustUsuallyManaged(userId)) { + mLockPatternUtils.setTrustUsuallyManaged(value, userId); + } } - } - break; - case MSG_REFRESH_DEVICE_LOCKED_FOR_USER: - if (msg.arg2 == 1) { - updateTrust(msg.arg1, 0 /* flags */, true /* isFromUnlock */, null); - } - final int unlockedUser = msg.getData().getInt( - REFRESH_DEVICE_LOCKED_EXCEPT_USER, UserHandle.USER_NULL); - refreshDeviceLockedForUser(msg.arg1, unlockedUser); - break; - case MSG_SCHEDULE_TRUST_TIMEOUT: - boolean shouldOverride = msg.arg1 == 1 ? true : false; - TimeoutType timeoutType = - msg.arg2 == 1 ? TimeoutType.TRUSTABLE : TimeoutType.TRUSTED; - handleScheduleTrustTimeout(shouldOverride, timeoutType); - break; - case MSG_REFRESH_TRUSTABLE_TIMERS_AFTER_AUTH: - TrustableTimeoutAlarmListener trustableAlarm = - mTrustableTimeoutAlarmListenerForUser.get(msg.arg1); - if (trustableAlarm != null && trustableAlarm.isQueued()) { - refreshTrustableTimers(msg.arg1); - } - break; + break; + case MSG_REFRESH_DEVICE_LOCKED_FOR_USER: + if (msg.arg2 == 1) { + updateTrust(msg.arg1, 0 /* flags */, true /* isFromUnlock */, null); + } + final int unlockedUser = msg.getData().getInt( + REFRESH_DEVICE_LOCKED_EXCEPT_USER, UserHandle.USER_NULL); + refreshDeviceLockedForUser(msg.arg1, unlockedUser); + break; + case MSG_SCHEDULE_TRUST_TIMEOUT: + boolean shouldOverride = msg.arg1 == 1 ? true : false; + TimeoutType timeoutType = + msg.arg2 == 1 ? TimeoutType.TRUSTABLE : TimeoutType.TRUSTED; + handleScheduleTrustTimeout(shouldOverride, timeoutType); + break; + case MSG_REFRESH_TRUSTABLE_TIMERS_AFTER_AUTH: + TrustableTimeoutAlarmListener trustableAlarm = + mTrustableTimeoutAlarmListenerForUser.get(msg.arg1); + if (trustableAlarm != null && trustableAlarm.isQueued()) { + refreshTrustableTimers(msg.arg1); + } + break; + } } - } - }; + }; + } private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override @@ -1960,8 +2035,8 @@ public class TrustManagerService extends SystemService { SparseBooleanArray mStartFromSuccessfulUnlock = new SparseBooleanArray(); - public StrongAuthTracker(Context context) { - super(context); + StrongAuthTracker(Context context, Looper looper) { + super(context, looper); } @Override diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/OWNERS b/services/tests/mockingservicestests/src/com/android/server/trust/OWNERS new file mode 100644 index 000000000000..e2c6ce15b51e --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/trust/OWNERS @@ -0,0 +1 @@ +include /core/java/android/service/trust/OWNERS diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java index 33870f1d3b86..9851bc1b4be3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java @@ -16,15 +16,26 @@ package com.android.server.trust; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.argThat; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyBoolean; + +import android.Manifest; import android.annotation.Nullable; +import android.app.trust.ITrustListener; +import android.app.trust.ITrustManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -36,11 +47,16 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.net.Uri; import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.test.TestLooper; import android.provider.Settings; import android.service.trust.TrustAgentService; import android.testing.TestableContext; +import android.view.IWindowManager; +import android.view.WindowManagerGlobal; import androidx.test.core.app.ApplicationProvider; @@ -55,13 +71,16 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; +import org.mockito.MockitoSession; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Collections; +import java.util.Random; public class TrustManagerServiceTest { @@ -255,6 +274,43 @@ public class TrustManagerServiceTest { systemTrustAgent1); } + @Test + public void reportEnabledTrustAgentsChangedInformsListener() throws RemoteException { + final LockPatternUtils utils = mock(LockPatternUtils.class); + final TrustManagerService service = new TrustManagerService(mMockContext, + new TrustManagerService.Injector(utils, mLooper.getLooper())); + final ITrustListener trustListener = mock(ITrustListener.class); + final IWindowManager windowManager = mock(IWindowManager.class); + final int userId = new Random().nextInt(); + + mMockContext.getTestablePermissions().setPermission(Manifest.permission.TRUST_LISTENER, + PERMISSION_GRANTED); + + when(utils.getKnownTrustAgents(anyInt())).thenReturn(new ArrayList<>()); + + MockitoSession mockSession = mockitoSession() + .initMocks(this) + .mockStatic(ServiceManager.class) + .mockStatic(WindowManagerGlobal.class) + .startMocking(); + + doReturn(windowManager).when(() -> { + WindowManagerGlobal.getWindowManagerService(); + }); + + service.onStart(); + ArgumentCaptor<IBinder> binderArgumentCaptor = ArgumentCaptor.forClass(IBinder.class); + verify(() -> ServiceManager.addService(eq(Context.TRUST_SERVICE), + binderArgumentCaptor.capture(), anyBoolean(), anyInt())); + ITrustManager manager = ITrustManager.Stub.asInterface(binderArgumentCaptor.getValue()); + manager.registerTrustListener(trustListener); + mLooper.dispatchAll(); + manager.reportEnabledTrustAgentsChanged(userId); + mLooper.dispatchAll(); + verify(trustListener).onEnabledTrustAgentsChanged(eq(userId)); + mockSession.finishMocking(); + } + private void addTrustAgent(ComponentName agentComponentName, boolean isSystemApp) { ApplicationInfo applicationInfo = new ApplicationInfo(); if (isSystemApp) { diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp index a1b888aef934..c216bced81f0 100644 --- a/tests/TrustTests/Android.bp +++ b/tests/TrustTests/Android.bp @@ -25,6 +25,7 @@ android_test { "androidx.test.rules", "androidx.test.ext.junit", "androidx.test.uiautomator_uiautomator", + "flag-junit", "mockito-target-minus-junit4", "servicestests-utils", "truth-prebuilt", diff --git a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt index f864fedf4e62..1dfd5c06167b 100644 --- a/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt +++ b/tests/TrustTests/src/android/trust/test/GrantAndRevokeTrustTest.kt @@ -16,6 +16,10 @@ package android.trust.test +import android.content.pm.PackageManager +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.DeviceFlagsValueProvider import android.service.trust.GrantTrustResult import android.trust.BaseTrustAgentService import android.trust.TrustTestActivity @@ -27,6 +31,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import androidx.test.uiautomator.UiDevice import com.android.server.testutils.mock +import org.junit.Assume.assumeFalse import org.junit.Before import org.junit.Rule import org.junit.Test @@ -45,6 +50,7 @@ class GrantAndRevokeTrustTest { private val activityScenarioRule = ActivityScenarioRule(TrustTestActivity::class.java) private val lockStateTrackingRule = LockStateTrackingRule() private val trustAgentRule = TrustAgentRule<GrantAndRevokeTrustAgent>() + private val packageManager = getInstrumentation().getTargetContext().getPackageManager() @get:Rule val rule: RuleChain = RuleChain @@ -52,6 +58,7 @@ class GrantAndRevokeTrustTest { .around(ScreenLockRule()) .around(lockStateTrackingRule) .around(trustAgentRule) + .around(DeviceFlagsValueProvider.createCheckFlagsRule()) @Before fun manageTrust() { @@ -72,7 +79,7 @@ class GrantAndRevokeTrustTest { trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {} uiDevice.sleep() - lockStateTrackingRule.assertUnlocked() + lockStateTrackingRule.assertUnlockedAndTrusted() } @Test @@ -86,6 +93,51 @@ class GrantAndRevokeTrustTest { } @Test + @RequiresFlagsEnabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + fun grantCannotActivelyUnlockDevice() { + // On automotive, trust agents can actively unlock the device. + assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) + + // Lock the device. + uiDevice.sleep() + lockStateTrackingRule.assertLocked() + + // Grant trust. + trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {} + + // The grant should not have unlocked the device. Wait a bit so that + // TrustManagerService probably will have finished processing the grant. + await() + lockStateTrackingRule.assertLocked() + + // Turn the screen on and off to cause TrustManagerService to refresh + // its deviceLocked state. Then verify the state is still locked. This + // part failed before the fix for b/296464083. + uiDevice.wakeUp() + uiDevice.sleep() + await() + lockStateTrackingRule.assertLocked() + } + + @Test + @RequiresFlagsDisabled(android.security.Flags.FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) + fun grantCouldCauseWrongDeviceLockedStateDueToBug() { + // On automotive, trust agents can actively unlock the device. + assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) + + // Verify that b/296464083 exists. That is, when the device is locked + // and a trust agent grants trust, the deviceLocked state incorrectly + // becomes false even though the device correctly remains locked. + uiDevice.sleep() + lockStateTrackingRule.assertLocked() + trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 10000, 0) {} + uiDevice.wakeUp() + uiDevice.sleep() + await() + lockStateTrackingRule.assertUnlockedButNotReally() + } + + @Test fun grantDoesNotCallBack() { val callback = mock<(GrantTrustResult) -> Unit>() trustAgentRule.agent.grantTrust(GRANT_MESSAGE, 0, 0, callback) diff --git a/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt b/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt index ae722477a2bc..96362b8e71dc 100644 --- a/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt +++ b/tests/TrustTests/src/android/trust/test/TemporaryAndRenewableTrustTest.kt @@ -102,7 +102,7 @@ class TemporaryAndRenewableTrustTest { trustAgentRule.agent.grantTrust( GRANT_MESSAGE, 0, FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) {} - lockStateTrackingRule.assertUnlocked() + lockStateTrackingRule.assertUnlockedAndTrusted() } @Test @@ -125,7 +125,7 @@ class TemporaryAndRenewableTrustTest { Log.i(TAG, "Callback received; status=${it.status}") result = it } - lockStateTrackingRule.assertUnlocked() + lockStateTrackingRule.assertUnlockedAndTrusted() wait("callback triggered") { result?.status == STATUS_UNLOCKED_BY_GRANT } } diff --git a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt index 1930a1c8bbb2..fe47fde9b268 100644 --- a/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/LockStateTrackingRule.kt @@ -16,6 +16,7 @@ package android.trust.test.lib +import android.app.KeyguardManager import android.app.trust.TrustManager import android.app.trust.TrustManager.TrustListener import android.content.Context @@ -27,18 +28,23 @@ import org.junit.runner.Description import org.junit.runners.model.Statement /** - * Rule for tracking the lock state of the device based on events emitted to [TrustListener]. + * Rule for tracking the trusted state of the device based on events emitted to + * [TrustListener]. Provides helper methods for verifying that the trusted + * state has a particular value and is consistent with (a) the keyguard "locked" + * (i.e. showing) value when applicable, and (b) the device locked value that is + * tracked by TrustManagerService and is queryable via KeyguardManager. */ class LockStateTrackingRule : TestRule { private val context: Context = getApplicationContext() - private val windowManager = WindowManagerGlobal.getWindowManagerService() + private val windowManager = checkNotNull(WindowManagerGlobal.getWindowManagerService()) + private val keyguardManager = context.getSystemService(KeyguardManager::class.java) as KeyguardManager - @Volatile lateinit var lockState: LockState + @Volatile lateinit var trustState: TrustState private set override fun apply(base: Statement, description: Description) = object : Statement() { override fun evaluate() { - lockState = LockState(locked = windowManager.isKeyguardLocked) + trustState = TrustState() val trustManager = context.getSystemService(TrustManager::class.java) as TrustManager val listener = Listener() @@ -52,12 +58,25 @@ class LockStateTrackingRule : TestRule { } fun assertLocked() { - wait("un-locked per TrustListener") { lockState.locked == true } - wait("keyguard lock") { windowManager.isKeyguardLocked } + wait("device locked") { keyguardManager.isDeviceLocked } + // isDeviceLocked implies isKeyguardLocked && !trusted. + wait("keyguard locked") { windowManager.isKeyguardLocked } + wait("not trusted") { trustState.trusted == false } } - fun assertUnlocked() { - wait("locked per TrustListener") { lockState.locked == false } + // TODO(b/299298338) remove this when removing FLAG_FIX_UNLOCKED_DEVICE_REQUIRED_KEYS + fun assertUnlockedButNotReally() { + wait("device unlocked") { !keyguardManager.isDeviceLocked } + wait("not trusted") { trustState.trusted == false } + wait("keyguard locked") { windowManager.isKeyguardLocked } + } + + fun assertUnlockedAndTrusted() { + wait("device unlocked") { !keyguardManager.isDeviceLocked } + wait("trusted") { trustState.trusted == true } + // Can't check for !isKeyguardLocked here, since isKeyguardLocked + // returns true in the case where the keyguard is dismissible with + // swipe, which is considered "device unlocked"! } inner class Listener : TrustListener { @@ -69,7 +88,7 @@ class LockStateTrackingRule : TestRule { trustGrantedMessages: MutableList<String> ) { Log.d(TAG, "Device became trusted=$enabled") - lockState = lockState.copy(locked = !enabled) + trustState = trustState.copy(trusted=enabled) } override fun onTrustManagedChanged(enabled: Boolean, userId: Int) { @@ -77,10 +96,13 @@ class LockStateTrackingRule : TestRule { override fun onTrustError(message: CharSequence) { } + + override fun onEnabledTrustAgentsChanged(userId: Int) { + } } - data class LockState( - val locked: Boolean? = null + data class TrustState( + val trusted: Boolean? = null ) companion object { diff --git a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt index 4189baae10cb..f1edca3ff86e 100644 --- a/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt +++ b/tests/TrustTests/src/android/trust/test/lib/ScreenLockRule.kt @@ -36,7 +36,7 @@ import org.junit.runners.model.Statement class ScreenLockRule : TestRule { private val context: Context = getApplicationContext() private val uiDevice = UiDevice.getInstance(getInstrumentation()) - private val windowManager = WindowManagerGlobal.getWindowManagerService() + private val windowManager = checkNotNull(WindowManagerGlobal.getWindowManagerService()) private val lockPatternUtils = LockPatternUtils(context) private var instantLockSavedValue = false diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index 0aaf3e8fd6c7..82bcfc2c1a8b 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -99,7 +99,7 @@ static bool isHidden(const char *root, const char *path) String8 fullPath(root); appendPath(fullPath, String8(path)); - FileType type = getFileType(fullPath); + FileType type = getFileType(fullPath.c_str()); int plen = strlen(path); @@ -287,19 +287,19 @@ int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int sta Vector<String8> subtags = AaptUtil::splitAndLowerCase(part, '+'); subtags.removeItemsAt(0); if (subtags.size() == 1) { - setLanguage(subtags[0]); + setLanguage(subtags[0].c_str()); } else if (subtags.size() == 2) { - setLanguage(subtags[0]); + setLanguage(subtags[0].c_str()); // The second tag can either be a region, a variant or a script. switch (subtags[1].size()) { case 2: case 3: - setRegion(subtags[1]); + setRegion(subtags[1].c_str()); break; case 4: if (isAlpha(subtags[1])) { - setScript(subtags[1]); + setScript(subtags[1].c_str()); break; } // This is not alphabetical, so we fall through to variant @@ -308,7 +308,7 @@ int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int sta case 6: case 7: case 8: - setVariant(subtags[1]); + setVariant(subtags[1].c_str()); break; default: fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name %s\n", @@ -317,14 +317,14 @@ int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int sta } } else if (subtags.size() == 3) { // The language is always the first subtag. - setLanguage(subtags[0]); + setLanguage(subtags[0].c_str()); // The second subtag can either be a script or a region code. // If its size is 4, it's a script code, else it's a region code. if (subtags[1].size() == 4) { - setScript(subtags[1]); + setScript(subtags[1].c_str()); } else if (subtags[1].size() == 2 || subtags[1].size() == 3) { - setRegion(subtags[1]); + setRegion(subtags[1].c_str()); } else { fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name %s\n", part.c_str()); return -1; @@ -333,15 +333,15 @@ int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int sta // The third tag can either be a region code (if the second tag was // a script), else a variant code. if (subtags[2].size() >= 4) { - setVariant(subtags[2]); + setVariant(subtags[2].c_str()); } else { - setRegion(subtags[2]); + setRegion(subtags[2].c_str()); } } else if (subtags.size() == 4) { - setLanguage(subtags[0]); - setScript(subtags[1]); - setRegion(subtags[2]); - setVariant(subtags[3]); + setLanguage(subtags[0].c_str()); + setScript(subtags[1].c_str()); + setRegion(subtags[2].c_str()); + setVariant(subtags[3].c_str()); } else { fprintf(stderr, "ERROR: Invalid BCP 47 tag in directory name: %s\n", part.c_str()); return -1; @@ -351,7 +351,7 @@ int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int sta } else { if ((part.length() == 2 || part.length() == 3) && isAlpha(part) && strcmp("car", part.c_str())) { - setLanguage(part); + setLanguage(part.c_str()); if (++currentIndex == size) { return size; } diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 800466aa587f..43a8b52f2766 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -401,7 +401,7 @@ static void printUsesImpliedPermission(const String8& name, const String8& reaso Vector<String8> getNfcAidCategories(AssetManager& assets, const String8& xmlPath, bool offHost, String8 *outError = NULL) { - Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); + Asset* aidAsset = assets.openNonAsset(xmlPath.c_str(), Asset::ACCESS_BUFFER); if (aidAsset == NULL) { if (outError != NULL) *outError = "xml resource does not exist"; return Vector<String8>(); @@ -2760,7 +2760,7 @@ int doPackage(Bundle* bundle) appendPath(dependencyFile, "R.java.d"); } // Make sure we have a clean dependency file to start with - fp = fopen(dependencyFile, "w"); + fp = fopen(dependencyFile.c_str(), "w"); fclose(fp); } @@ -2849,7 +2849,7 @@ int doPackage(Bundle* bundle) if (bundle->getGenDependencies()) { // Now that writeResourceSymbols or writeAPK has taken care of writing // the targets to our dependency file, we'll write the prereqs - fp = fopen(dependencyFile, "a+"); + fp = fopen(dependencyFile.c_str(), "a+"); fprintf(fp, " : "); bool includeRaw = (outputAPKFile != NULL); err = writeDependencyPreReqs(bundle, assets, fp, includeRaw); diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 3a198fd43d48..7e4e186ec320 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -924,7 +924,7 @@ status_t massageManifest(Bundle* bundle, ResourceTable* table, sp<XMLNode> root) if (bundle->getCompileSdkVersion() != 0) { if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "compileSdkVersion", - String8::format("%d", bundle->getCompileSdkVersion()), + String8::format("%d", bundle->getCompileSdkVersion()).c_str(), errorOnFailedInsert, true)) { return UNKNOWN_ERROR; } @@ -932,21 +932,21 @@ status_t massageManifest(Bundle* bundle, ResourceTable* table, sp<XMLNode> root) if (bundle->getCompileSdkVersionCodename() != "") { if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "compileSdkVersionCodename", - bundle->getCompileSdkVersionCodename(), errorOnFailedInsert, true)) { + bundle->getCompileSdkVersionCodename().c_str(), errorOnFailedInsert, true)) { return UNKNOWN_ERROR; } } if (bundle->getPlatformBuildVersionCode() != "") { if (!addTagAttribute(root, "", "platformBuildVersionCode", - bundle->getPlatformBuildVersionCode(), errorOnFailedInsert, true)) { + bundle->getPlatformBuildVersionCode().c_str(), errorOnFailedInsert, true)) { return UNKNOWN_ERROR; } } if (bundle->getPlatformBuildVersionName() != "") { if (!addTagAttribute(root, "", "platformBuildVersionName", - bundle->getPlatformBuildVersionName(), errorOnFailedInsert, true)) { + bundle->getPlatformBuildVersionName().c_str(), errorOnFailedInsert, true)) { return UNKNOWN_ERROR; } } @@ -1210,7 +1210,7 @@ status_t generateAndroidManifestForSplit(Bundle* bundle, const sp<AaptAssets>& a sp<XMLNode> manifest = XMLNode::newElement(filename, String16(), String16("manifest")); // Add the 'package' attribute which is set to the package name. - const char* packageName = assets->getPackage(); + const char* packageName = assets->getPackage().c_str(); const char* manifestPackageNameOverride = bundle->getManifestPackageNameOverride(); if (manifestPackageNameOverride != NULL) { packageName = manifestPackageNameOverride; diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp index 8d0268393433..1af8d6f67bd3 100644 --- a/tools/aapt/StringPool.cpp +++ b/tools/aapt/StringPool.cpp @@ -472,13 +472,13 @@ status_t StringPool::writeStringBlock(const sp<AaptFile>& pool) ENCODE_LENGTH(strings, sizeof(uint8_t), encSize) - strncpy((char*)strings, encStr, encSize+1); + strncpy((char*)strings, encStr.c_str(), encSize + 1); } else { char16_t* strings = (char16_t*)dat; ENCODE_LENGTH(strings, sizeof(char16_t), strSize) - strcpy16_htod(strings, ent.value); + strcpy16_htod(strings, ent.value.c_str()); } strPos += totalSize; @@ -592,7 +592,7 @@ ssize_t StringPool::offsetForString(const String16& val) const ssize_t res = indices != NULL && indices->size() > 0 ? indices->itemAt(0) : -1; if (kIsDebug) { printf("Offset for string %s: %zd (%s)\n", String8(val).c_str(), res, - res >= 0 ? String8(mEntries[mEntryArray[res]].value).c_str() : String8()); + res >= 0 ? String8(mEntries[mEntryArray[res]].value).c_str() : ""); } return res; } diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp index a887ac947835..1a648c01f631 100644 --- a/tools/aapt/XMLNode.cpp +++ b/tools/aapt/XMLNode.cpp @@ -559,7 +559,7 @@ status_t parseXMLResource(const sp<AaptFile>& file, ResXMLTree* outTree, root->removeWhitespace(stripAll, cDataTags); if (kIsDebug) { - printf("Input XML from %s:\n", (const char*)file->getPrintableSource()); + printf("Input XML from %s:\n", file->getPrintableSource().c_str()); root->print(); } sp<AaptFile> rsc = new AaptFile(String8(), AaptGroupEntry(), String8()); diff --git a/tools/aapt/ZipEntry.cpp b/tools/aapt/ZipEntry.cpp index 5339285f5667..6886993fbfa1 100644 --- a/tools/aapt/ZipEntry.cpp +++ b/tools/aapt/ZipEntry.cpp @@ -18,6 +18,8 @@ // Access to entries in a Zip archive. // +#define _POSIX_THREAD_SAFE_FUNCTIONS // For mingw localtime_r(). + #define LOG_TAG "zip" #include "ZipEntry.h" @@ -337,39 +339,26 @@ time_t ZipEntry::getModWhen(void) const /* * Set the CDE/LFH timestamp from UNIX time. */ -void ZipEntry::setModWhen(time_t when) -{ -#if !defined(_WIN32) - struct tm tmResult; -#endif - time_t even; - unsigned short zdate, ztime; - - struct tm* ptm; - +void ZipEntry::setModWhen(time_t when) { /* round up to an even number of seconds */ - even = (time_t)(((unsigned long)(when) + 1) & (~1)); + time_t even = (time_t)(((unsigned long)(when) + 1) & (~1)); /* expand */ -#if !defined(_WIN32) - ptm = localtime_r(&even, &tmResult); -#else - ptm = localtime(&even); -#endif + struct tm tmResult; + struct tm* ptm = localtime_r(&even, &tmResult); int year; year = ptm->tm_year; if (year < 80) year = 80; - zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; - ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1; + unsigned short zdate = (year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday; + unsigned short ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1; mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime; mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate; } - /* * =========================================================================== * ZipEntry::LocalFileHeader diff --git a/tools/aapt/tests/AaptGroupEntry_test.cpp b/tools/aapt/tests/AaptGroupEntry_test.cpp index bf5ca59a81c8..8621e9be7010 100644 --- a/tools/aapt/tests/AaptGroupEntry_test.cpp +++ b/tools/aapt/tests/AaptGroupEntry_test.cpp @@ -24,7 +24,7 @@ using android::String8; static ::testing::AssertionResult TestParse(AaptGroupEntry& entry, const String8& dirName, String8* outType) { - if (entry.initFromDirName(dirName, outType)) { + if (entry.initFromDirName(dirName.c_str(), outType)) { return ::testing::AssertionSuccess() << dirName << " was successfully parsed"; } return ::testing::AssertionFailure() << dirName << " could not be parsed"; diff --git a/tools/aapt2/DominatorTree_test.cpp b/tools/aapt2/DominatorTree_test.cpp index a0679a65b9fd..087f456ec084 100644 --- a/tools/aapt2/DominatorTree_test.cpp +++ b/tools/aapt2/DominatorTree_test.cpp @@ -50,8 +50,8 @@ class PrettyPrinter : public DominatorTree::Visitor { private: void VisitConfig(const DominatorTree::Node* node, const int indent) { auto config_string = node->value()->config.toString(); - buffer_ << std::string(indent, ' ') << (config_string.empty() ? "<default>" : config_string) - << std::endl; + buffer_ << std::string(indent, ' ') + << (config_string.empty() ? "<default>" : config_string.c_str()) << std::endl; } void VisitNode(const DominatorTree::Node* node, const int indent) { diff --git a/tools/aapt2/compile/InlineXmlFormatParser.h b/tools/aapt2/compile/InlineXmlFormatParser.h index 4300023e7726..3a5161b828da 100644 --- a/tools/aapt2/compile/InlineXmlFormatParser.h +++ b/tools/aapt2/compile/InlineXmlFormatParser.h @@ -21,8 +21,8 @@ #include <vector> #include "android-base/macros.h" - #include "process/IResourceTableConsumer.h" +#include "xml/XmlDom.h" namespace aapt { diff --git a/tools/lint/common/Android.bp b/tools/lint/common/Android.bp index 898f88b8759c..8bfbfe5f60b3 100644 --- a/tools/lint/common/Android.bp +++ b/tools/lint/common/Android.bp @@ -27,3 +27,30 @@ java_library_host { libs: ["lint_api"], kotlincflags: ["-Xjvm-default=all"], } + +java_defaults { + name: "AndroidLintCheckerTestDefaults", + srcs: ["checks/src/test/java/**/*.kt"], + static_libs: [ + "junit", + "lint", + "lint_tests", + ], + test_options: { + unit_test: true, + tradefed_options: [ + { + // lint bundles in some classes that were built with older versions + // of libraries, and no longer load. Since tradefed tries to load + // all classes in the jar to look for tests, it crashes loading them. + // Exclude these classes from tradefed's search. + name: "exclude-paths", + value: "org/apache", + }, + { + name: "exclude-paths", + value: "META-INF", + }, + ], + }, +} diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt index ab6d871d6ea6..ab6d871d6ea6 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt index e03d92ab44a0..e03d92ab44a0 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt index d41fee3fc0dc..d41fee3fc0dc 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt diff --git a/tools/lint/fix/soong_lint_fix.py b/tools/lint/fix/soong_lint_fix.py index cd4d778d1dec..acc0ad043171 100644 --- a/tools/lint/fix/soong_lint_fix.py +++ b/tools/lint/fix/soong_lint_fix.py @@ -29,6 +29,39 @@ PATH_PREFIX = "out/soong/.intermediates" PATH_SUFFIX = "android_common/lint" FIX_ZIP = "suggested-fixes.zip" + +class SoongModule: + """A Soong module to lint. + + The constructor takes the name of the module (for example, + "framework-minus-apex"). find() must be called to extract the intermediate + module path from Soong's module-info.json + """ + def __init__(self, name): + self._name = name + + def find(self, module_info): + """Finds the module in the loaded module_info.json.""" + if self._name not in module_info: + raise Exception(f"Module {self._name} not found!") + + partial_path = module_info[self._name]["path"][0] + print(f"Found module {partial_path}/{self._name}.") + self._path = f"{PATH_PREFIX}/{partial_path}/{self._name}/{PATH_SUFFIX}" + + @property + def name(self): + return self._name + + @property + def lint_report(self): + return f"{self._path}/lint-report.txt" + + @property + def suggested_fixes(self): + return f"{self._path}/{FIX_ZIP}" + + class SoongLintFix: """ This class creates a command line tool that will @@ -53,16 +86,14 @@ class SoongLintFix: self._parser = _setup_parser() self._args = None self._kwargs = None - self._path = None - self._target = None - + self._modules = [] - def run(self, additional_setup=None, custom_fix=None): + def run(self): """ Run the script """ self._setup() - self._find_module() + self._find_modules() self._lint() if not self._args.no_fix: @@ -87,8 +118,6 @@ class SoongLintFix: os.chdir(ANDROID_BUILD_TOP) - - def _find_module(self): print("Refreshing soong modules...") try: os.mkdir(ANDROID_PRODUCT_OUT) @@ -97,48 +126,47 @@ class SoongLintFix: subprocess.call(f"{SOONG_UI} --make-mode {PRODUCT_OUT}/module-info.json", **self._kwargs) print("done.") + + def _find_modules(self): with open(f"{ANDROID_PRODUCT_OUT}/module-info.json") as f: module_info = json.load(f) - if self._args.module not in module_info: - sys.exit(f"Module {self._args.module} not found!") - - module_path = module_info[self._args.module]["path"][0] - print(f"Found module {module_path}/{self._args.module}.") - - self._path = f"{PATH_PREFIX}/{module_path}/{self._args.module}/{PATH_SUFFIX}" - self._target = f"{self._path}/lint-report.txt" - + for module_name in self._args.modules: + module = SoongModule(module_name) + module.find(module_info) + self._modules.append(module) def _lint(self): print("Cleaning up any old lint results...") - try: - os.remove(f"{self._target}") - os.remove(f"{self._path}/{FIX_ZIP}") - except FileNotFoundError: - pass + for module in self._modules: + try: + os.remove(f"{module.lint_report}") + os.remove(f"{module.suggested_fixes}") + except FileNotFoundError: + pass print("done.") - print(f"Generating {self._target}") - subprocess.call(f"{SOONG_UI} --make-mode {self._target}", **self._kwargs) + target = " ".join([ module.lint_report for module in self._modules ]) + print(f"Generating {target}") + subprocess.call(f"{SOONG_UI} --make-mode {target}", **self._kwargs) print("done.") - def _fix(self): - print("Copying suggested fixes to the tree...") - with zipfile.ZipFile(f"{self._path}/{FIX_ZIP}") as zip: - for name in zip.namelist(): - if name.startswith("out") or not name.endswith(".java"): - continue - with zip.open(name) as src, open(f"{ANDROID_BUILD_TOP}/{name}", "wb") as dst: - shutil.copyfileobj(src, dst) + for module in self._modules: + print(f"Copying suggested fixes for {module.name} to the tree...") + with zipfile.ZipFile(f"{module.suggested_fixes}") as zip: + for name in zip.namelist(): + if name.startswith("out") or not name.endswith(".java"): + continue + with zip.open(name) as src, open(f"{ANDROID_BUILD_TOP}/{name}", "wb") as dst: + shutil.copyfileobj(src, dst) print("done.") - def _print(self): - print("### lint-report.txt ###", end="\n\n") - with open(self._target, "r") as f: - print(f.read()) + for module in self._modules: + print(f"### lint-report.txt {module.name} ###", end="\n\n") + with open(module.lint_report, "r") as f: + print(f.read()) def _setup_parser(): @@ -151,7 +179,8 @@ def _setup_parser(): **Gotcha**: You must have run `source build/envsetup.sh` and `lunch` first. """, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('module', + parser.add_argument('modules', + nargs='+', help='The soong build module to run ' '(e.g. framework-minus-apex or services.core.unboosted)') @@ -170,4 +199,4 @@ def _setup_parser(): return parser if __name__ == "__main__": - SoongLintFix().run()
\ No newline at end of file + SoongLintFix().run() diff --git a/tools/lint/framework/Android.bp b/tools/lint/framework/Android.bp index 30a6daaef2a4..5acdf436ae08 100644 --- a/tools/lint/framework/Android.bp +++ b/tools/lint/framework/Android.bp @@ -37,28 +37,9 @@ java_library_host { java_test_host { name: "AndroidFrameworkLintCheckerTest", + defaults: ["AndroidLintCheckerTestDefaults"], srcs: ["checks/src/test/java/**/*.kt"], static_libs: [ "AndroidFrameworkLintChecker", - "junit", - "lint", - "lint_tests", ], - test_options: { - unit_test: true, - tradefed_options: [ - { - // lint bundles in some classes that were built with older versions - // of libraries, and no longer load. Since tradefed tries to load - // all classes in the jar to look for tests, it crashes loading them. - // Exclude these classes from tradefed's search. - name: "exclude-paths", - value: "org/apache", - }, - { - name: "exclude-paths", - value: "META-INF", - }, - ], - }, } diff --git a/tools/lint/global/Android.bp b/tools/lint/global/Android.bp index bedb7bd78a29..3e74171814ab 100644 --- a/tools/lint/global/Android.bp +++ b/tools/lint/global/Android.bp @@ -38,28 +38,9 @@ java_library_host { java_test_host { name: "AndroidGlobalLintCheckerTest", + defaults: ["AndroidLintCheckerTestDefaults"], srcs: ["checks/src/test/java/**/*.kt"], static_libs: [ "AndroidGlobalLintChecker", - "junit", - "lint", - "lint_tests", ], - test_options: { - unit_test: true, - tradefed_options: [ - { - // lint bundles in some classes that were built with older versions - // of libraries, and no longer load. Since tradefed tries to load - // all classes in the jar to look for tests, it crashes loading them. - // Exclude these classes from tradefed's search. - name: "exclude-paths", - value: "org/apache", - }, - { - name: "exclude-paths", - value: "META-INF", - }, - ], - }, } diff --git a/tools/lint/utils/Android.bp b/tools/lint/utils/Android.bp new file mode 100644 index 000000000000..75e8d6863c20 --- /dev/null +++ b/tools/lint/utils/Android.bp @@ -0,0 +1,45 @@ +// Copyright (C) 2023 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +java_library_host { + name: "AndroidUtilsLintChecker", + srcs: ["checks/src/main/java/**/*.kt"], + plugins: ["auto_service_plugin"], + libs: [ + "auto_service_annotations", + "lint_api", + ], + static_libs: [ + "AndroidCommonLint", + ], + kotlincflags: ["-Xjvm-default=all"], +} + +java_test_host { + name: "AndroidUtilsLintCheckerTest", + defaults: ["AndroidLintCheckerTestDefaults"], + srcs: ["checks/src/test/java/**/*.kt"], + static_libs: [ + "AndroidUtilsLintChecker", + ], +} diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt new file mode 100644 index 000000000000..fa61c42ef8e6 --- /dev/null +++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 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.google.android.lint + +import com.android.tools.lint.client.api.IssueRegistry +import com.android.tools.lint.client.api.Vendor +import com.android.tools.lint.detector.api.CURRENT_API +import com.google.android.lint.aidl.AnnotatedAidlCounter +import com.google.auto.service.AutoService + +@AutoService(IssueRegistry::class) +@Suppress("UnstableApiUsage") +class AndroidUtilsIssueRegistry : IssueRegistry() { + override val issues = listOf( + AnnotatedAidlCounter.ISSUE_ANNOTATED_AIDL_COUNTER, + ) + + override val api: Int + get() = CURRENT_API + + override val minApi: Int + get() = 8 + + override val vendor: Vendor = Vendor( + vendorName = "Android", + feedbackUrl = "http://b/issues/new?component=315013", + contact = "tweek@google.com" + ) +} diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/AnnotatedAidlCounter.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/AnnotatedAidlCounter.kt new file mode 100644 index 000000000000..f0ec3f44f6c4 --- /dev/null +++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/AnnotatedAidlCounter.kt @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2023 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.google.android.lint.aidl + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Context +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Location +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import org.jetbrains.uast.UBlockExpression +import org.jetbrains.uast.UMethod + +import java.util.TreeMap + +/** + * Count the number of AIDL interfaces. Reports the number of annotated and + * non-annotated methods. + */ +@Suppress("UnstableApiUsage") +class AnnotatedAidlCounter : AidlImplementationDetector() { + + private data class Stat( + var unannotated: Int = 0, + var enforced: Int = 0, + var notRequired: Int = 0, + ) + + private var packagesStats: TreeMap<String, Stat> = TreeMap<String, Stat>() + + override fun visitAidlMethod( + context: JavaContext, + node: UMethod, + interfaceName: String, + body: UBlockExpression + ) { + val packageName = context.uastFile?.packageName ?: "<unknown>" + var packageStat = packagesStats.getOrDefault(packageName, Stat()) + when { + node.hasAnnotation(ANNOTATION_ENFORCE_PERMISSION) -> packageStat.enforced += 1 + node.hasAnnotation(ANNOTATION_REQUIRES_NO_PERMISSION) -> packageStat.notRequired += 1 + else -> packageStat.unannotated += 1 + } + packagesStats.put(packageName, packageStat) + // context.driver.client.log(null, "%s.%s#%s".format(packageName, interfaceName, node.name)) + } + + override fun afterCheckRootProject(context: Context) { + var total = Stat() + for ((packageName, stat) in packagesStats) { + context.client.log(null, "package $packageName => $stat") + total.unannotated += stat.unannotated + total.enforced += stat.enforced + total.notRequired += stat.notRequired + } + val location = Location.create(context.project.dir) + context.report( + ISSUE_ANNOTATED_AIDL_COUNTER, + location, + "module ${context.project.name} => $total" + ) + } + + companion object { + + @JvmField + val ISSUE_ANNOTATED_AIDL_COUNTER = Issue.create( + id = "AnnotatedAidlCounter", + briefDescription = "Statistics on the number of annotated AIDL methods.", + explanation = "", + category = Category.SECURITY, + priority = 5, + severity = Severity.INFORMATIONAL, + implementation = Implementation( + AnnotatedAidlCounter::class.java, + Scope.JAVA_FILE_SCOPE + ), + ) + } +} diff --git a/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/AnnotatedAidlCounterTest.kt b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/AnnotatedAidlCounterTest.kt new file mode 100644 index 000000000000..692b7da243c9 --- /dev/null +++ b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/AnnotatedAidlCounterTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 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.google.android.lint.aidl + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue + +@Suppress("UnstableApiUsage") +class AnnotatedAidlCounterTest : LintDetectorTest() { + override fun getDetector(): Detector = AnnotatedAidlCounter() + + override fun getIssues(): List<Issue> = listOf( + AnnotatedAidlCounter.ISSUE_ANNOTATED_AIDL_COUNTER, + ) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + /** No issue scenario */ + + fun testDoesNotDetectIssuesCorrectAnnotationOnMethod() { + lint().files(java( + """ + package test.pkg; + import android.annotation.EnforcePermission; + public class TestClass2 extends IFooMethod.Stub { + @Override + @EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethod() {} + } + """).indented(), + *stubs + ) + .run() + .expect(""" + app: Information: module app => Stat(unannotated=0, enforced=1, notRequired=0) [AnnotatedAidlCounter] + 0 errors, 0 warnings + """) + } + + // A service with permission annotation on the method. + private val interfaceIFooMethodStub: TestFile = java( + """ + public interface IFooMethod extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IFooMethod {} + @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethod(); + } + """ + ).indented() + + // A service without any permission annotation. + private val interfaceIBarStub: TestFile = java( + """ + public interface IBar extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IBar { + @Override + public void testMethod() {} + } + public void testMethod(); + } + """ + ).indented() + + private val manifestPermissionStub: TestFile = java( + """ + package android.Manifest; + class permission { + public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"; + } + """ + ).indented() + + private val enforcePermissionAnnotationStub: TestFile = java( + """ + package android.annotation; + public @interface EnforcePermission {} + """ + ).indented() + + private val stubs = arrayOf(interfaceIFooMethodStub, interfaceIBarStub, + manifestPermissionStub, enforcePermissionAnnotationStub) +} diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp index 0d7d5f949a08..6cae3ecc6e44 100644 --- a/tools/validatekeymaps/Main.cpp +++ b/tools/validatekeymaps/Main.cpp @@ -165,7 +165,7 @@ static bool validateFile(const char* filename) { case FileType::INPUT_DEVICE_CONFIGURATION: { android::base::Result<std::unique_ptr<PropertyMap>> propertyMap = - PropertyMap::load(String8(filename)); + PropertyMap::load(String8(filename).c_str()); if (!propertyMap.ok()) { error("Error %d parsing input device configuration file.\n\n", propertyMap.error().code()); |