diff options
94 files changed, 1291 insertions, 845 deletions
diff --git a/Android.bp b/Android.bp index 5796fb17046c..12bc90680dd5 100644 --- a/Android.bp +++ b/Android.bp @@ -653,6 +653,33 @@ gensrcs { output_extension: "srcjar", } +gensrcs { + name: "framework-cppstream-protos", + depfile: true, + + tools: [ + "aprotoc", + "protoc-gen-cppstream", + ], + + cmd: "mkdir -p $(genDir) " + + "&& $(location aprotoc) " + + " --plugin=$(location protoc-gen-cppstream) " + + " --dependency_out=$(depfile) " + + " --cppstream_out=$(genDir) " + + " -Iexternal/protobuf/src " + + " -I . " + + " $(in)", + + srcs: [ + ":ipconnectivity-proto-src", + "core/proto/**/*.proto", + "libs/incident/**/*.proto", + ], + + output_extension: "proto.h", +} + filegroup { name: "framework-annotations", srcs: [ @@ -1010,43 +1037,6 @@ aidl_interface { }, } -gensrcs { - name: "gen-platform-proto-constants", - depfile: true, - - tools: [ - "aprotoc", - "protoc-gen-cppstream", - ], - - srcs: [ - "core/proto/android/os/backtrace.proto", - "core/proto/android/os/batterytype.proto", - "core/proto/android/os/cpufreq.proto", - "core/proto/android/os/cpuinfo.proto", - "core/proto/android/os/data.proto", - "core/proto/android/os/kernelwake.proto", - "core/proto/android/os/pagetypeinfo.proto", - "core/proto/android/os/procrank.proto", - "core/proto/android/os/ps.proto", - "core/proto/android/os/system_properties.proto", - "core/proto/android/util/event_log_tags.proto", - "core/proto/android/util/log.proto", - ], - - // Append protoc-gen-cppstream tool's PATH otherwise aprotoc can't find the plugin tool - cmd: "mkdir -p $(genDir) " + - "&& $(location aprotoc) " + - " --plugin=$(location protoc-gen-cppstream) " + - " --dependency_out=$(depfile) " + - " --cppstream_out=$(genDir) " + - " -Iexternal/protobuf/src " + - " -I . " + - " $(in)", - - output_extension: "proto.h", -} - subdirs = [ "cmds/*", diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java index d59270c6a51b..96110e1541f8 100644 --- a/apex/media/framework/java/android/media/MediaParser.java +++ b/apex/media/framework/java/android/media/MediaParser.java @@ -15,6 +15,7 @@ */ package android.media; +import android.annotation.CheckResult; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.Uri; @@ -32,6 +33,7 @@ import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.SeekMap.SeekPoints; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.amr.AmrExtractor; +import com.google.android.exoplayer2.extractor.flac.FlacExtractor; import com.google.android.exoplayer2.extractor.flv.FlvExtractor; import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor; @@ -382,6 +384,7 @@ public final class MediaParser { * parse the input. */ @NonNull + @CheckResult private static UnrecognizedInputFormatException createForExtractors( @NonNull String... extractorNames) { StringBuilder builder = new StringBuilder(); @@ -536,7 +539,7 @@ public final class MediaParser { } } if (mExtractor == null) { - UnrecognizedInputFormatException.createForExtractors(mExtractorNamesPool); + throw UnrecognizedInputFormatException.createForExtractors(mExtractorNamesPool); } return true; } @@ -912,6 +915,7 @@ public final class MediaParser { extractorFactoriesByName.put("exo.Ac4Extractor", Ac4Extractor::new); extractorFactoriesByName.put("exo.AdtsExtractor", AdtsExtractor::new); extractorFactoriesByName.put("exo.AmrExtractor", AmrExtractor::new); + extractorFactoriesByName.put("exo.FlacExtractor", FlacExtractor::new); extractorFactoriesByName.put("exo.FlvExtractor", FlvExtractor::new); extractorFactoriesByName.put("exo.FragmentedMp4Extractor", FragmentedMp4Extractor::new); extractorFactoriesByName.put("exo.MatroskaExtractor", MatroskaExtractor::new); diff --git a/api/current.txt b/api/current.txt index 6e3a6562b146..81c4c922b730 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26799,7 +26799,6 @@ package android.media { method public abstract void onSelectRoute(@NonNull String, @NonNull String); method public abstract void onSetVolume(@NonNull String, int); method public abstract void onTransferToRoute(@NonNull String, @NonNull String); - method public abstract void onUpdateVolume(@NonNull String, int); field public static final long REQUEST_ID_UNKNOWN = 0L; // 0x0L field public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService"; } @@ -35688,6 +35687,7 @@ package android.os { field public static final String INCREMENTAL; field public static final int PREVIEW_SDK_INT; field public static final String RELEASE; + field @NonNull public static final String RELEASE_OR_CODENAME; field @Deprecated public static final String SDK; field public static final int SDK_INT; field public static final String SECURITY_PATCH; diff --git a/api/system-current.txt b/api/system-current.txt index 97914ddf7064..7903fbab696a 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1473,9 +1473,9 @@ package android.bluetooth { public final class BluetoothAdapter { method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean connectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); method public boolean disableBLE(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean disconnectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean disconnectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice); method public boolean enableBLE(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean enableNoAutoConnect(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean factoryReset(); diff --git a/cmds/incident_helper/Android.bp b/cmds/incident_helper/Android.bp index 64f4c667820d..f07743ec2ee6 100644 --- a/cmds/incident_helper/Android.bp +++ b/cmds/incident_helper/Android.bp @@ -44,7 +44,7 @@ cc_defaults { "src/ih_util.cpp", ], - generated_headers: ["gen-platform-proto-constants"], + generated_headers: ["framework-cppstream-protos"], shared_libs: [ "libbase", diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp index cc724a626baf..c47526abad53 100644 --- a/cmds/incidentd/Android.bp +++ b/cmds/incidentd/Android.bp @@ -43,7 +43,7 @@ cc_binary { ], local_include_dirs: ["src"], - generated_headers: ["gen-platform-proto-constants"], + generated_headers: ["framework-cppstream-protos"], proto: { type: "lite", @@ -98,7 +98,7 @@ cc_test { ], local_include_dirs: ["src"], - generated_headers: ["gen-platform-proto-constants"], + generated_headers: ["framework-cppstream-protos"], srcs: [ "tests/**/*.cpp", diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 8e5309fcbb7d..3a2472efb601 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -65,7 +65,6 @@ cc_defaults { "src/config/ConfigListener.cpp", "src/config/ConfigManager.cpp", "src/experiment_ids.proto", - "src/external/GpuStatsPuller.cpp", "src/external/Perfetto.cpp", "src/external/PullResultReceiver.cpp", "src/external/puller_util.cpp", @@ -111,7 +110,7 @@ cc_defaults { ], cflags: [ - // "-DNEW_ENCODING_SCHEME", + "-DNEW_ENCODING_SCHEME", ], local_include_dirs: [ @@ -122,19 +121,18 @@ cc_defaults { "android.frameworks.stats@1.0", "libbase", "libcutils", - "liblog", "libprotoutil", "libstatslog", - "libstatssocket", + "libstatsmetadata", "libsysutils", ], shared_libs: [ "libbinder", - "libgraphicsenv", "libhidlbase", "libincident", + "liblog", "libservices", - "libstatsmetadata", + "libstatssocket", "libutils", ], } @@ -161,7 +159,7 @@ genrule { ], } -cc_library_shared { +cc_library_static { name: "libstatsmetadata", host_supported: true, generated_sources: [ @@ -278,7 +276,6 @@ cc_test { "tests/e2e/PartialBucket_e2e_test.cpp", "tests/e2e/ValueMetric_pull_e2e_test.cpp", "tests/e2e/WakelockDuration_e2e_test.cpp", - "tests/external/GpuStatsPuller_test.cpp", "tests/external/puller_util_test.cpp", "tests/external/StatsCallbackPuller_test.cpp", "tests/external/StatsPuller_test.cpp", diff --git a/cmds/statsd/src/external/GpuStatsPuller.cpp b/cmds/statsd/src/external/GpuStatsPuller.cpp deleted file mode 100644 index 3229ba82fe3c..000000000000 --- a/cmds/statsd/src/external/GpuStatsPuller.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GpuStatsPuller.h" - -#include <binder/IServiceManager.h> -#include <graphicsenv/GpuStatsInfo.h> -#include <graphicsenv/IGpuService.h> - -#include "logd/LogEvent.h" - -#include "stats_log_util.h" -#include "statslog.h" - -namespace android { -namespace os { -namespace statsd { - -using android::util::ProtoReader; - -GpuStatsPuller::GpuStatsPuller(const int tagId) : StatsPuller(tagId) { -} - -static sp<IGpuService> getGpuService() { - const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu")); - if (!binder) { - ALOGE("Failed to get gpu service"); - return nullptr; - } - - return interface_cast<IGpuService>(binder); -} - -static bool pullGpuStatsGlobalInfo(const sp<IGpuService>& gpuService, - std::vector<std::shared_ptr<LogEvent>>* data) { - std::vector<GpuStatsGlobalInfo> stats; - status_t status = gpuService->getGpuStatsGlobalInfo(&stats); - if (status != OK) { - return false; - } - - data->clear(); - data->reserve(stats.size()); - for (const auto& info : stats) { - std::shared_ptr<LogEvent> event = make_shared<LogEvent>( - android::util::GPU_STATS_GLOBAL_INFO, getWallClockNs(), getElapsedRealtimeNs()); - if (!event->write(info.driverPackageName)) return false; - if (!event->write(info.driverVersionName)) return false; - if (!event->write((int64_t)info.driverVersionCode)) return false; - if (!event->write(info.driverBuildTime)) return false; - if (!event->write((int64_t)info.glLoadingCount)) return false; - if (!event->write((int64_t)info.glLoadingFailureCount)) return false; - if (!event->write((int64_t)info.vkLoadingCount)) return false; - if (!event->write((int64_t)info.vkLoadingFailureCount)) return false; - if (!event->write(info.vulkanVersion)) return false; - if (!event->write(info.cpuVulkanVersion)) return false; - if (!event->write(info.glesVersion)) return false; - if (!event->write((int64_t)info.angleLoadingCount)) return false; - if (!event->write((int64_t)info.angleLoadingFailureCount)) return false; - event->init(); - data->emplace_back(event); - } - - return true; -} - -static bool pullGpuStatsAppInfo(const sp<IGpuService>& gpuService, - std::vector<std::shared_ptr<LogEvent>>* data) { - std::vector<GpuStatsAppInfo> stats; - status_t status = gpuService->getGpuStatsAppInfo(&stats); - if (status != OK) { - return false; - } - - data->clear(); - data->reserve(stats.size()); - for (const auto& info : stats) { - std::shared_ptr<LogEvent> event = make_shared<LogEvent>( - android::util::GPU_STATS_APP_INFO, getWallClockNs(), getElapsedRealtimeNs()); - if (!event->write(info.appPackageName)) return false; - if (!event->write((int64_t)info.driverVersionCode)) return false; - if (!event->writeBytes(int64VectorToProtoByteString(info.glDriverLoadingTime))) { - return false; - } - if (!event->writeBytes(int64VectorToProtoByteString(info.vkDriverLoadingTime))) { - return false; - } - if (!event->writeBytes(int64VectorToProtoByteString(info.angleDriverLoadingTime))) { - return false; - } - if (!event->write(info.cpuVulkanInUse)) return false; - if (!event->write(info.falsePrerotation)) return false; - if (!event->write(info.gles1InUse)) return false; - event->init(); - data->emplace_back(event); - } - - return true; -} - -bool GpuStatsPuller::PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) { - const sp<IGpuService> gpuService = getGpuService(); - if (!gpuService) { - return false; - } - - switch (mTagId) { - case android::util::GPU_STATS_GLOBAL_INFO: - return pullGpuStatsGlobalInfo(gpuService, data); - case android::util::GPU_STATS_APP_INFO: - return pullGpuStatsAppInfo(gpuService, data); - default: - break; - } - - return false; -} - -static std::string protoOutputStreamToByteString(ProtoOutputStream& proto) { - if (!proto.size()) return ""; - - std::string byteString; - sp<ProtoReader> reader = proto.data(); - while (reader->readBuffer() != nullptr) { - const size_t toRead = reader->currentToRead(); - byteString.append((char*)reader->readBuffer(), toRead); - reader->move(toRead); - } - - if (byteString.size() != proto.size()) return ""; - - return byteString; -} - -std::string int64VectorToProtoByteString(const std::vector<int64_t>& value) { - if (value.empty()) return ""; - - ProtoOutputStream proto; - for (const auto& ele : value) { - proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED | - 1 /* field id */, - (long long)ele); - } - - return protoOutputStreamToByteString(proto); -} - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/src/external/GpuStatsPuller.h b/cmds/statsd/src/external/GpuStatsPuller.h deleted file mode 100644 index 2da199c51e0f..000000000000 --- a/cmds/statsd/src/external/GpuStatsPuller.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "StatsPuller.h" - -namespace android { -namespace os { -namespace statsd { - -/** - * Pull GpuStats from GpuService. - */ -class GpuStatsPuller : public StatsPuller { -public: - explicit GpuStatsPuller(const int tagId); - bool PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) override; -}; - -// convert a int64_t vector into a byte string for proto message like: -// message RepeatedInt64Wrapper { -// repeated int64 value = 1; -// } -std::string int64VectorToProtoByteString(const std::vector<int64_t>& value); - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 15d7e33d63fd..3ceff7529440 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -32,7 +32,6 @@ #include "../logd/LogEvent.h" #include "../stats_log_util.h" #include "../statscompanion_util.h" -#include "GpuStatsPuller.h" #include "StatsCallbackPuller.h" #include "TrainInfoPuller.h" #include "statslog.h" @@ -51,15 +50,6 @@ StatsPullerManager::StatsPullerManager() : kAllPullAtomInfo({ // TrainInfo. {{.atomTag = android::util::TRAIN_INFO}, new TrainInfoPuller()}, - - // GpuStatsGlobalInfo - {{.atomTag = android::util::GPU_STATS_GLOBAL_INFO}, - new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)}, - - // GpuStatsAppInfo - {{.atomTag = android::util::GPU_STATS_APP_INFO}, - new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)}, - }), mNextPullTimeNs(NO_ALARM_UPDATE) { } diff --git a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp deleted file mode 100644 index ae92705aff4c..000000000000 --- a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#undef LOG_TAG -#define LOG_TAG "GpuStatsPuller_test" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <graphicsenv/GpuStatsInfo.h> -#include <log/log.h> - -#include "src/external/GpuStatsPuller.h" -#include "statslog.h" - -#ifdef __ANDROID__ - -namespace android { -namespace os { -namespace statsd { - -// clang-format off -static const std::string DRIVER_PACKAGE_NAME = "TEST_DRIVER"; -static const std::string DRIVER_VERSION_NAME = "TEST_DRIVER_VERSION"; -static const std::string APP_PACKAGE_NAME = "TEST_APP"; -static const int64_t TIMESTAMP_WALLCLOCK = 111; -static const int64_t TIMESTAMP_ELAPSED = 222; -static const int64_t DRIVER_VERSION_CODE = 333; -static const int64_t DRIVER_BUILD_TIME = 444; -static const int64_t GL_LOADING_COUNT = 3; -static const int64_t GL_LOADING_FAILURE_COUNT = 1; -static const int64_t VK_LOADING_COUNT = 4; -static const int64_t VK_LOADING_FAILURE_COUNT = 0; -static const int64_t ANGLE_LOADING_COUNT = 2; -static const int64_t ANGLE_LOADING_FAILURE_COUNT = 1; -static const int64_t GL_DRIVER_LOADING_TIME_0 = 555; -static const int64_t GL_DRIVER_LOADING_TIME_1 = 666; -static const int64_t VK_DRIVER_LOADING_TIME_0 = 777; -static const int64_t VK_DRIVER_LOADING_TIME_1 = 888; -static const int64_t VK_DRIVER_LOADING_TIME_2 = 999; -static const int64_t ANGLE_DRIVER_LOADING_TIME_0 = 1010; -static const int64_t ANGLE_DRIVER_LOADING_TIME_1 = 1111; -static const int32_t VULKAN_VERSION = 1; -static const int32_t CPU_VULKAN_VERSION = 2; -static const int32_t GLES_VERSION = 3; -static const bool CPU_VULKAN_IN_USE = true; -static const bool FALSE_PREROTATION = true; -static const bool GLES_1_IN_USE = true; -static const size_t NUMBER_OF_VALUES_GLOBAL = 13; -static const size_t NUMBER_OF_VALUES_APP = 8; -// clang-format on - -class MockGpuStatsPuller : public GpuStatsPuller { -public: - MockGpuStatsPuller(const int tagId, vector<std::shared_ptr<LogEvent>>* data) - : GpuStatsPuller(tagId), mData(data){}; - -private: - bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override { - *data = *mData; - return true; - } - - vector<std::shared_ptr<LogEvent>>* mData; -}; - -class GpuStatsPuller_test : public ::testing::Test { -public: - GpuStatsPuller_test() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - } - - ~GpuStatsPuller_test() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); - } -}; - -TEST_F(GpuStatsPuller_test, PullGpuStatsGlobalInfo) { - vector<std::shared_ptr<LogEvent>> inData, outData; - std::shared_ptr<LogEvent> event = make_shared<LogEvent>(android::util::GPU_STATS_GLOBAL_INFO, - TIMESTAMP_WALLCLOCK, TIMESTAMP_ELAPSED); - EXPECT_TRUE(event->write(DRIVER_PACKAGE_NAME)); - EXPECT_TRUE(event->write(DRIVER_VERSION_NAME)); - EXPECT_TRUE(event->write(DRIVER_VERSION_CODE)); - EXPECT_TRUE(event->write(DRIVER_BUILD_TIME)); - EXPECT_TRUE(event->write(GL_LOADING_COUNT)); - EXPECT_TRUE(event->write(GL_LOADING_FAILURE_COUNT)); - EXPECT_TRUE(event->write(VK_LOADING_COUNT)); - EXPECT_TRUE(event->write(VK_LOADING_FAILURE_COUNT)); - EXPECT_TRUE(event->write(VULKAN_VERSION)); - EXPECT_TRUE(event->write(CPU_VULKAN_VERSION)); - EXPECT_TRUE(event->write(GLES_VERSION)); - EXPECT_TRUE(event->write(ANGLE_LOADING_COUNT)); - EXPECT_TRUE(event->write(ANGLE_LOADING_FAILURE_COUNT)); - event->init(); - inData.emplace_back(event); - MockGpuStatsPuller mockPuller(android::util::GPU_STATS_GLOBAL_INFO, &inData); - mockPuller.ForceClearCache(); - mockPuller.Pull(&outData); - - ASSERT_EQ(1, outData.size()); - EXPECT_EQ(android::util::GPU_STATS_GLOBAL_INFO, outData[0]->GetTagId()); - ASSERT_EQ(NUMBER_OF_VALUES_GLOBAL, outData[0]->size()); - EXPECT_EQ(DRIVER_PACKAGE_NAME, outData[0]->getValues()[0].mValue.str_value); - EXPECT_EQ(DRIVER_VERSION_NAME, outData[0]->getValues()[1].mValue.str_value); - EXPECT_EQ(DRIVER_VERSION_CODE, outData[0]->getValues()[2].mValue.long_value); - EXPECT_EQ(DRIVER_BUILD_TIME, outData[0]->getValues()[3].mValue.long_value); - EXPECT_EQ(GL_LOADING_COUNT, outData[0]->getValues()[4].mValue.long_value); - EXPECT_EQ(GL_LOADING_FAILURE_COUNT, outData[0]->getValues()[5].mValue.long_value); - EXPECT_EQ(VK_LOADING_COUNT, outData[0]->getValues()[6].mValue.long_value); - EXPECT_EQ(VK_LOADING_FAILURE_COUNT, outData[0]->getValues()[7].mValue.long_value); - EXPECT_EQ(VULKAN_VERSION, outData[0]->getValues()[8].mValue.int_value); - EXPECT_EQ(CPU_VULKAN_VERSION, outData[0]->getValues()[9].mValue.int_value); - EXPECT_EQ(GLES_VERSION, outData[0]->getValues()[10].mValue.int_value); - EXPECT_EQ(ANGLE_LOADING_COUNT, outData[0]->getValues()[11].mValue.long_value); - EXPECT_EQ(ANGLE_LOADING_FAILURE_COUNT, outData[0]->getValues()[12].mValue.long_value); -} - -TEST_F(GpuStatsPuller_test, PullGpuStatsAppInfo) { - vector<std::shared_ptr<LogEvent>> inData, outData; - std::shared_ptr<LogEvent> event = make_shared<LogEvent>(android::util::GPU_STATS_APP_INFO, - TIMESTAMP_WALLCLOCK, TIMESTAMP_ELAPSED); - EXPECT_TRUE(event->write(APP_PACKAGE_NAME)); - EXPECT_TRUE(event->write(DRIVER_VERSION_CODE)); - std::vector<int64_t> glDriverLoadingTime; - glDriverLoadingTime.emplace_back(GL_DRIVER_LOADING_TIME_0); - glDriverLoadingTime.emplace_back(GL_DRIVER_LOADING_TIME_1); - std::vector<int64_t> vkDriverLoadingTime; - vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_0); - vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_1); - vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_2); - std::vector<int64_t> angleDriverLoadingTime; - angleDriverLoadingTime.emplace_back(ANGLE_DRIVER_LOADING_TIME_0); - angleDriverLoadingTime.emplace_back(ANGLE_DRIVER_LOADING_TIME_1); - EXPECT_TRUE(event->write(int64VectorToProtoByteString(glDriverLoadingTime))); - EXPECT_TRUE(event->write(int64VectorToProtoByteString(vkDriverLoadingTime))); - EXPECT_TRUE(event->write(int64VectorToProtoByteString(angleDriverLoadingTime))); - EXPECT_TRUE(event->write(CPU_VULKAN_IN_USE)); - EXPECT_TRUE(event->write(FALSE_PREROTATION)); - EXPECT_TRUE(event->write(GLES_1_IN_USE)); - event->init(); - inData.emplace_back(event); - MockGpuStatsPuller mockPuller(android::util::GPU_STATS_APP_INFO, &inData); - mockPuller.ForceClearCache(); - mockPuller.Pull(&outData); - - ASSERT_EQ(1, outData.size()); - EXPECT_EQ(android::util::GPU_STATS_APP_INFO, outData[0]->GetTagId()); - ASSERT_EQ(NUMBER_OF_VALUES_APP, outData[0]->size()); - EXPECT_EQ(APP_PACKAGE_NAME, outData[0]->getValues()[0].mValue.str_value); - EXPECT_EQ(DRIVER_VERSION_CODE, outData[0]->getValues()[1].mValue.long_value); - EXPECT_EQ(int64VectorToProtoByteString(glDriverLoadingTime), - outData[0]->getValues()[2].mValue.str_value); - EXPECT_EQ(int64VectorToProtoByteString(vkDriverLoadingTime), - outData[0]->getValues()[3].mValue.str_value); - EXPECT_EQ(int64VectorToProtoByteString(angleDriverLoadingTime), - outData[0]->getValues()[4].mValue.str_value); - EXPECT_EQ(CPU_VULKAN_IN_USE, outData[0]->getValues()[5].mValue.int_value); - EXPECT_EQ(FALSE_PREROTATION, outData[0]->getValues()[6].mValue.int_value); - EXPECT_EQ(GLES_1_IN_USE, outData[0]->getValues()[7].mValue.int_value); -} - -} // namespace statsd -} // namespace os -} // namespace android -#else -GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 2e93d43f7c15..01ccb86fb129 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1861,15 +1861,19 @@ public final class BluetoothAdapter { } /** - * Connects all enabled and supported bluetooth profiles between the local and remote device + * Connects all enabled and supported bluetooth profiles between the local and remote device. + * Connection is asynchronous and you should listen to each profile's broadcast intent + * ACTION_CONNECTION_STATE_CHANGED to verify whether connection was successful. For example, + * to verify a2dp is connected, you would listen for + * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED} * * @param device is the remote device with which to connect these profiles - * @return true if all profiles successfully connected, false if an error occurred + * @return true if message sent to try to connect all profiles, false if an error occurred * * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean connectAllEnabledProfiles(@NonNull BluetoothDevice device) { try { mServiceLock.readLock().lock(); @@ -1886,15 +1890,19 @@ public final class BluetoothAdapter { } /** - * Disconnects all enabled and supported bluetooth profiles between the local and remote device + * Disconnects all enabled and supported bluetooth profiles between the local and remote device. + * Disconnection is asynchronous and you should listen to each profile's broadcast intent + * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example, + * to verify a2dp is disconnected, you would listen for + * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED} * * @param device is the remote device with which to disconnect these profiles - * @return true if all profiles successfully disconnected, false if an error occurred + * @return true if message sent to try to disconnect all profiles, false if an error occurred * * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean disconnectAllEnabledProfiles(@NonNull BluetoothDevice device) { try { mServiceLock.readLock().lock(); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index a29173469ffb..70b2db70a9e8 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -240,6 +240,13 @@ public class Build { public static final String RELEASE = getString("ro.build.version.release"); /** + * The version string we show to the user; may be {@link #RELEASE} or + * {@link #CODENAME} if not a final release build. + */ + @NonNull public static final String RELEASE_OR_CODENAME = getString( + "ro.build.version.release_or_codename"); + + /** * The base OS build the product is based on. */ public static final String BASE_OS = SystemProperties.get("ro.build.version.base_os", ""); diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 44f12a6adf60..21a1e0f0a108 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -34,9 +34,11 @@ import android.text.TextUtils; import android.util.Log; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; +import java.util.List; /** * Provides access to environment variables. @@ -539,12 +541,21 @@ public class Environment { @SystemApi public static @NonNull Collection<File> getInternalMediaDirectories() { final ArrayList<File> res = new ArrayList<>(); - res.add(new File(Environment.getRootDirectory(), "media")); - res.add(new File(Environment.getOemDirectory(), "media")); - res.add(new File(Environment.getProductDirectory(), "media")); + addCanonicalFile(res, new File(Environment.getRootDirectory(), "media")); + addCanonicalFile(res, new File(Environment.getOemDirectory(), "media")); + addCanonicalFile(res, new File(Environment.getProductDirectory(), "media")); return res; } + private static void addCanonicalFile(List<File> list, File file) { + try { + list.add(file.getCanonicalFile()); + } catch (IOException e) { + Log.w(TAG, "Failed to resolve " + file + ": " + e); + list.add(file); + } + } + /** * Return the primary shared/external storage directory. This directory may * not currently be accessible if it has been mounted by the user on their diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java index b6f5138a6582..adfa885f121e 100644 --- a/core/java/android/provider/Telephony.java +++ b/core/java/android/provider/Telephony.java @@ -5205,6 +5205,7 @@ public final class Telephony { /** * TelephonyProvider column name for allowed network types. Indicate which network types * are allowed. Default is -1. + * <P>Type: BIGINT (long) </P> */ public static final String ALLOWED_NETWORK_TYPES = "allowed_network_types"; } diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java index 848868a5532f..3ff6f549e337 100644 --- a/core/java/android/service/textclassifier/TextClassifierService.java +++ b/core/java/android/service/textclassifier/TextClassifierService.java @@ -41,6 +41,7 @@ import android.util.Slog; import android.view.textclassifier.ConversationActions; import android.view.textclassifier.SelectionEvent; import android.view.textclassifier.TextClassification; +import android.view.textclassifier.TextClassificationConstants; import android.view.textclassifier.TextClassificationContext; import android.view.textclassifier.TextClassificationManager; import android.view.textclassifier.TextClassificationSessionId; @@ -404,22 +405,27 @@ public abstract class TextClassifierService extends Service { */ @NonNull public static TextClassifier getDefaultTextClassifierImplementation(@NonNull Context context) { - final String defaultTextClassifierPackageName = - context.getPackageManager().getDefaultTextClassifierPackageName(); - if (TextUtils.isEmpty(defaultTextClassifierPackageName)) { - return TextClassifier.NO_OP; - } - if (defaultTextClassifierPackageName.equals(context.getPackageName())) { - throw new RuntimeException( - "The default text classifier itself should not call the" - + "getDefaultTextClassifierImplementation() method."); - } final TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class); - if (tcm != null) { + if (tcm == null) { + return TextClassifier.NO_OP; + } + TextClassificationConstants settings = new TextClassificationConstants(); + if (settings.getUseDefaultTextClassifierAsDefaultImplementation()) { + final String defaultTextClassifierPackageName = + context.getPackageManager().getDefaultTextClassifierPackageName(); + if (TextUtils.isEmpty(defaultTextClassifierPackageName)) { + return TextClassifier.NO_OP; + } + if (defaultTextClassifierPackageName.equals(context.getPackageName())) { + throw new RuntimeException( + "The default text classifier itself should not call the" + + "getDefaultTextClassifierImplementation() method."); + } return tcm.getTextClassifier(TextClassifier.DEFAULT_SERVICE); + } else { + return tcm.getTextClassifier(TextClassifier.LOCAL); } - return TextClassifier.NO_OP; } /** @hide **/ diff --git a/core/java/android/timezone/CountryTimeZones.java b/core/java/android/timezone/CountryTimeZones.java index ab2c4fc1bf23..ee3a8a79d5d7 100644 --- a/core/java/android/timezone/CountryTimeZones.java +++ b/core/java/android/timezone/CountryTimeZones.java @@ -18,7 +18,6 @@ package android.timezone; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SuppressLint; import android.icu.util.TimeZone; import java.util.ArrayList; @@ -206,27 +205,47 @@ public final class CountryTimeZones { } /** - * Returns a time zone for the country, if there is one, that matches the desired properties. If - * there are multiple matches and the {@code bias} is one of them then it is returned, otherwise - * an arbitrary match is returned based on the {@link #getEffectiveTimeZoneMappingsAt(long)} - * ordering. + * Returns a time zone for the country, if there is one, that matches the supplied properties. + * If there are multiple matches and the {@code bias} is one of them then it is returned, + * otherwise an arbitrary match is returned based on the {@link + * #getEffectiveTimeZoneMappingsAt(long)} ordering. * + * @param whenMillis the UTC time to match against + * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference * @param totalOffsetMillis the offset from UTC at {@code whenMillis} * @param isDst the Daylight Savings Time state at {@code whenMillis}. {@code true} means DST, - * {@code false} means not DST, {@code null} means unknown - * @param dstOffsetMillis the part of {@code totalOffsetMillis} contributed by DST, only used if - * {@code isDst} is {@code true}. The value can be {@code null} if the DST offset is - * unknown - * @param whenMillis the UTC time to match against - * @param bias the time zone to prefer, can be {@code null} + * {@code false} means not DST + * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if + * there is no match */ @Nullable - public OffsetResult lookupByOffsetWithBias(int totalOffsetMillis, @Nullable Boolean isDst, - @SuppressLint("AutoBoxing") @Nullable Integer dstOffsetMillis, long whenMillis, - @Nullable TimeZone bias) { + public OffsetResult lookupByOffsetWithBias(long whenMillis, @Nullable TimeZone bias, + int totalOffsetMillis, boolean isDst) { libcore.timezone.CountryTimeZones.OffsetResult delegateOffsetResult = mDelegate.lookupByOffsetWithBias( - totalOffsetMillis, isDst, dstOffsetMillis, whenMillis, bias); + whenMillis, bias, totalOffsetMillis, isDst); + return delegateOffsetResult == null ? null : + new OffsetResult( + delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch()); + } + + /** + * Returns a time zone for the country, if there is one, that matches the supplied properties. + * If there are multiple matches and the {@code bias} is one of them then it is returned, + * otherwise an arbitrary match is returned based on the {@link + * #getEffectiveTimeZoneMappingsAt(long)} ordering. + * + * @param whenMillis the UTC time to match against + * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference + * @param totalOffsetMillis the offset from UTC at {@code whenMillis} + * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if + * there is no match + */ + @Nullable + public OffsetResult lookupByOffsetWithBias(long whenMillis, @Nullable TimeZone bias, + int totalOffsetMillis) { + libcore.timezone.CountryTimeZones.OffsetResult delegateOffsetResult = + mDelegate.lookupByOffsetWithBias(whenMillis, bias, totalOffsetMillis); return delegateOffsetResult == null ? null : new OffsetResult( delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch()); diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 36f4e5361ea6..4b3afbaada64 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -80,7 +80,7 @@ public class TimeUtils { return null; } CountryTimeZones.OffsetResult offsetResult = countryTimeZones.lookupByOffsetWithBias( - offsetMillis, isDst, null /* dstOffsetMillis */, whenMillis, bias); + whenMillis, bias, offsetMillis, isDst); return offsetResult != null ? offsetResult.getTimeZone() : null; } diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java index ed69513b7f69..3d5ac58e7704 100644 --- a/core/java/android/view/textclassifier/TextClassificationConstants.java +++ b/core/java/android/view/textclassifier/TextClassificationConstants.java @@ -17,6 +17,7 @@ package android.view.textclassifier; import android.annotation.Nullable; +import android.content.Context; import android.provider.DeviceConfig; import com.android.internal.annotations.VisibleForTesting; @@ -167,6 +168,16 @@ public final class TextClassificationConstants { static final String TEXT_CLASSIFIER_SERVICE_PACKAGE_OVERRIDE = "textclassifier_service_package_override"; + /** + * Whether to use the default system text classifier as the default text classifier + * implementation. The local text classifier is used if it is {@code false}. + * + * @see android.service.textclassifier.TextClassifierService#getDefaultTextClassifierImplementation(Context) + */ + // TODO: Once the system health experiment is done, remove this together with local TC. + private static final String USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL = + "use_default_system_text_classifier_as_default_impl"; + private static final String DEFAULT_TEXT_CLASSIFIER_SERVICE_PACKAGE_OVERRIDE = null; private static final boolean LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT = true; private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT = true; @@ -209,7 +220,8 @@ public final class TextClassificationConstants { private static final boolean TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT = true; private static final boolean TRANSLATE_IN_CLASSIFICATION_ENABLED_DEFAULT = true; private static final boolean DETECT_LANGUAGES_FROM_TEXT_ENABLED_DEFAULT = true; - private static final float[] LANG_ID_CONTEXT_SETTINGS_DEFAULT = new float[] {20f, 1.0f, 0.4f}; + private static final float[] LANG_ID_CONTEXT_SETTINGS_DEFAULT = new float[]{20f, 1.0f, 0.4f}; + private static final boolean USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL_DEFAULT = true; @Nullable public String getTextClassifierServicePackageOverride() { @@ -331,6 +343,13 @@ public final class TextClassificationConstants { LANG_ID_CONTEXT_SETTINGS, LANG_ID_CONTEXT_SETTINGS_DEFAULT); } + public boolean getUseDefaultTextClassifierAsDefaultImplementation() { + return DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_TEXTCLASSIFIER, + USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL, + USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL_DEFAULT); + } + void dump(IndentingPrintWriter pw) { pw.println("TextClassificationConstants:"); pw.increaseIndent(); @@ -378,6 +397,8 @@ public final class TextClassificationConstants { .println(); pw.printPair("textclassifier_service_package_override", getTextClassifierServicePackageOverride()).println(); + pw.printPair("use_default_system_text_classifier_as_default_impl", + getUseDefaultTextClassifierAsDefaultImplementation()).println(); pw.decreaseIndent(); } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 7fd41508dfc3..4e4a9837b32c 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -454,15 +454,17 @@ public class Editor { aspectRatio = 5.5f; } - final Paint.FontMetrics fontMetrics = mTextView.getPaint().getFontMetrics(); - final float sourceHeight = fontMetrics.descent - fontMetrics.ascent; + final Layout layout = mTextView.getLayout(); + final int line = layout.getLineForOffset(mTextView.getSelectionStart()); + final int sourceHeight = + layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line); // Slightly increase the height to avoid tooLargeTextForMagnifier() returns true. int height = (int)(sourceHeight * zoom) + 2; int width = (int)(aspectRatio * height); params.setFishEyeStyle() .setSize(width, height) - .setSourceSize(width, Math.round(sourceHeight)) + .setSourceSize(width, sourceHeight) .setElevation(0) .setInitialZoom(zoom) .setClippingEnabled(false); @@ -5041,7 +5043,7 @@ public class Editor { // Vertically snap to middle of current line. showPosInView.y = ((mTextView.getLayout().getLineTop(lineNumber) - + mTextView.getLayout().getLineBottom(lineNumber)) / 2.0f + + mTextView.getLayout().getLineBottomWithoutSpacing(lineNumber)) / 2.0f + mTextView.getTotalPaddingTop() - mTextView.getScrollY()) * mTextViewScaleY; return true; } diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 78d4e61ea953..db714c2439bd 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -266,6 +266,7 @@ public class Toast { * targeting API level {@link Build.VERSION_CODES#R} or higher that are in the background * will not have custom toast views displayed. */ + @Deprecated public View getView() { return mNextView; } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index a43e4fe118a9..65cad834d5be 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -2424,6 +2424,10 @@ public class ChooserActivity extends ResolverActivity implements offset += findViewById(R.id.content_preview_container).getHeight(); } + if (hasWorkProfile() && ENABLE_TABBED_VIEW) { + offset += findViewById(R.id.tabs).getHeight(); + } + int directShareHeight = 0; rowsToShow = Math.min(4, rowsToShow); for (int i = 0, childCount = recyclerView.getChildCount(); diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index c6ed624d73ac..518911e652f6 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -323,7 +323,7 @@ public class RuntimeInit { result.append(System.getProperty("java.vm.version")); // such as 1.1.0 result.append(" (Linux; U; Android "); - String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5" + String version = Build.VERSION.RELEASE_OR_CODENAME; // "1.0" or "3.4b5" result.append(version.length() > 0 ? version : "1.0"); // add the model for the release build diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index a6e08d2cecc1..fc0a2ef6041a 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2562,7 +2562,7 @@ enum PageId { // CATEGORY: SETTINGS // OS: R OPEN_SUPPORTED_LINKS = 1824; - + // OPEN: Settings > Display > Dark theme > Set start time dialog DIALOG_DARK_THEME_SET_START_TIME = 1825; @@ -2573,4 +2573,9 @@ enum PageId { // CATEGORY: SETTINGS // OS: R VIBRATE_FOR_CALLS = 1827; + + // OPEN: Settings > Connected devices > Connection preferences > NFC + // CATEGORY: SETTINGS + // OS: R + CONNECTION_DEVICE_ADVANCED_NFC = 1828; } diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index 8adcc9ed905d..bf4cdee72b2d 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -52,6 +52,7 @@ import "frameworks/base/core/proto/android/service/package.proto"; import "frameworks/base/core/proto/android/service/print.proto"; import "frameworks/base/core/proto/android/service/procstats.proto"; import "frameworks/base/core/proto/android/service/restricted_image.proto"; +import "frameworks/base/core/proto/android/service/sensor_service.proto"; import "frameworks/base/core/proto/android/service/usb.proto"; import "frameworks/base/core/proto/android/util/event_log_tags.proto"; import "frameworks/base/core/proto/android/util/log.proto"; @@ -492,6 +493,11 @@ message IncidentProto { (section).args = "contexthub --proto" ]; + optional android.service.SensorServiceProto sensor_service = 3053 [ + (section).type = SECTION_DUMPSYS, + (section).args = "sensorservice --proto" + ]; + // Reserved for OEMs. extensions 50000 to 100000; } diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 0a2fd7093a49..2d2ead455a4d 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -27,7 +27,6 @@ import "frameworks/base/core/proto/android/content/component_name.proto"; import "frameworks/base/core/proto/android/content/configuration.proto"; import "frameworks/base/core/proto/android/content/intent.proto"; import "frameworks/base/core/proto/android/content/package_item_info.proto"; -import "frameworks/base/core/proto/android/graphics/rect.proto"; import "frameworks/base/core/proto/android/internal/processstats.proto"; import "frameworks/base/core/proto/android/os/bundle.proto"; import "frameworks/base/core/proto/android/os/looper.proto"; diff --git a/core/proto/android/server/notificationhistory.proto b/core/proto/android/server/notificationhistory.proto index 1e6ee3f1a3a8..6749719be124 100644 --- a/core/proto/android/server/notificationhistory.proto +++ b/core/proto/android/server/notificationhistory.proto @@ -17,8 +17,6 @@ syntax = "proto2"; package com.android.server.notification; -import "frameworks/base/core/proto/android/server/enums.proto"; - option java_multiple_files = true; // On disk data store for historical notifications diff --git a/core/proto/android/service/sensor_service.proto b/core/proto/android/service/sensor_service.proto new file mode 100644 index 000000000000..8598f86a7f28 --- /dev/null +++ b/core/proto/android/service/sensor_service.proto @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2020 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. + */ + +syntax = "proto2"; +package android.service; + +import "frameworks/base/core/proto/android/privacy.proto"; + +option java_multiple_files = true; + +/* + * Notes: + * 1. When using ProtoOutputStream to write this proto message, must call + * token = ProtoOutputStream#start(fieldId) before and ProtoOutputStream#end(token) after + * writing a nested message. + * 2. Never reuse a proto field number. When removing a field, mark it as reserved. + */ + +// Proto dump of android::SensorService. dumpsys sensorservice --proto +message SensorServiceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + enum OperatingModeEnum { + OP_MODE_UNKNOWN = 0; + OP_MODE_NORMAL = 1; + OP_MODE_RESTRICTED = 2; + OP_MODE_DATA_INJECTION = 3; + } + + optional int64 current_time_ms = 1; + optional SensorDeviceProto sensor_device = 2; + optional SensorListProto sensors = 3; + optional SensorFusionProto fusion_state = 4; + optional SensorEventsProto sensor_events = 5; + repeated ActiveSensorProto active_sensors = 6; + optional int32 socket_buffer_size = 7; + optional int32 socket_buffer_size_in_events = 8; + optional bool wake_lock_acquired = 9; + optional OperatingModeEnum operating_mode = 10; + // Non-empty only if operating_mode is RESTRICTED or DATA_INJECTION. + optional string whitelisted_package = 11; + optional bool sensor_privacy = 12; + repeated SensorEventConnectionProto active_connections = 13; + repeated SensorDirectConnectionProto direct_connections = 14; + repeated SensorRegistrationInfoProto previous_registrations = 15; +} + +// Proto dump of android::SensorDevice +message SensorDeviceProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool initialized = 1; + optional int32 total_sensors = 2; + optional int32 active_sensors = 3; + + message SensorProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 handle = 1; + optional int32 active_count = 2; + repeated float sampling_period_ms = 3; + optional float sampling_period_selected = 4; + repeated float batching_period_ms = 5; + optional float batching_period_selected = 6; + } + repeated SensorProto sensors = 4; +} + +// Proto dump of android::SensorServiceUtil::SensorList +message SensorListProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + enum ReportingModeEnum { + RM_UNKNOWN = 0; + RM_CONTINUOUS = 1; + RM_ON_CHANGE = 2; + RM_ONE_SHOT = 3; + RM_SPECIAL_TRIGGER = 4; + } + + message SensorProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 handle = 1; + optional string name = 2; + optional string vendor = 3; + optional int32 version = 4; + optional string string_type = 5; + optional int32 type = 6; + optional string required_permission = 7; + optional int32 flags = 8; + optional ReportingModeEnum reporting_mode = 9; + optional int32 max_delay_us = 10; + optional int32 min_delay_us = 11; + optional int32 fifo_max_event_count = 12; + optional int32 fifo_reserved_event_count = 13; + optional bool is_wakeup = 14; + optional bool data_injection_supported = 15; + optional bool is_dynamic = 16; + optional bool has_additional_info = 17; + optional int32 highest_rate_level = 18; + optional bool ashmem = 19; + optional bool gralloc = 20; + optional float min_value = 21; + optional float max_value = 22; + optional float resolution = 23; + optional float power_usage = 24; + } + repeated SensorProto sensors = 1; +} + + +// Proto dump of android::SensorFusion +message SensorFusionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + message FusionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional bool enabled = 1; + optional int32 num_clients = 2; + optional float estimated_gyro_rate = 3; + optional float attitude_x = 4; + optional float attitude_y = 5; + optional float attitude_z = 6; + optional float attitude_w = 7; + optional float attitude_length = 8; + optional float bias_x = 9; + optional float bias_y = 10; + optional float bias_z = 11; + } + optional FusionProto fusion_9axis = 1; + optional FusionProto fusion_nomag = 2; + optional FusionProto fusion_nogyro = 3; +} + +// Proto dump of android::SensorServiceUtil::RecentEventLogger +message SensorEventsProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + message Event { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional float timestamp_sec = 1; + optional int64 wall_timestamp_ms = 2; + optional bool masked = 3; + optional int64 int64_data = 4; + repeated float float_array = 5; + } + + message RecentEventsLog { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string name = 1; + optional int32 recent_events_count = 2; + repeated Event events = 3; + } + repeated RecentEventsLog recent_events_logs = 1; +} + +message ActiveSensorProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string name = 1; + optional int32 handle = 2; + optional int32 num_connections = 3; +} + +// Proto dump of android::SensorService::SensorDirectConnection +message SensorDirectConnectionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + message SensorProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int32 sensor = 1; + optional int32 rate = 2; + } + + optional string package_name = 1; + optional int32 hal_channel_handle = 2; + optional int32 num_sensor_activated = 3; + repeated SensorProto sensors = 4; +} + +// Proto dump of android::SensorService::SensorEventConnection +message SensorEventConnectionProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + message FlushInfoProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional string sensor_name = 1; + optional int32 sensor_handle = 2; + optional bool first_flush_pending = 3; + optional int32 pending_flush_events_to_send = 4; + } + + enum OperatingModeEnum { + OP_MODE_UNKNOWN = 0; + OP_MODE_NORMAL = 1; + OP_MODE_RESTRICTED = 2; + OP_MODE_DATA_INJECTION = 3; + } + + optional OperatingModeEnum operating_mode = 1; + optional string package_name = 2; + optional int32 wake_lock_ref_count = 3; + optional int32 uid = 4; + optional int32 cache_size = 5; + optional int32 max_cache_size = 6; + repeated FlushInfoProto flush_infos = 7; + optional int32 events_received = 8; + optional int32 events_sent = 9; + optional int32 events_cache = 10; + optional int32 events_dropped = 11; + optional int32 total_acks_needed = 12; + optional int32 total_acks_received = 13; +} + +// Proto dump of android::SensorService::SensorRegistrationInfo +message SensorRegistrationInfoProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + optional int64 timestamp_sec = 1; + optional int32 sensor_handle = 2; + optional string package_name = 3; + optional int32 pid = 4; + optional int32 uid = 5; + optional int64 sampling_rate_us = 6; + optional int64 max_report_latency_us = 7; + optional bool activated = 8; +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index efa7d591fa38..27d41d4d5ca4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4878,6 +4878,19 @@ <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" android:protectionLevel="signature|installer" /> + <!-- Allows an app to log compat change usage. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.LOG_COMPAT_CHANGE" + android:protectionLevel="signature|privileged" /> + <!-- Allows an app to read compat change config. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" + android:protectionLevel="signature|privileged" /> + <!-- Allows an app to override compat change config. + @hide <p>Not for use by third-party applications.</p> --> + <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" + android:protectionLevel="signature|privileged" /> + <!-- Allows input events to be monitored. Very dangerous! @hide --> <permission android:name="android.permission.MONITOR_INPUT" android:protectionLevel="signature" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index b2d08a9730fc..31e68e88c0a8 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4343,4 +4343,7 @@ Determines whether the specified key groups can be used to wake up the device. --> <bool name="config_wakeOnDpadKeyPress">true</bool> <bool name="config_wakeOnAssistKeyPress">true</bool> + + <!-- Whether to default to an expanded list of users on the lock screen user switcher. --> + <bool name="config_expandLockScreenUserSwitcher">false</bool> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c59d25f10b0b..2453bb18577f 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3863,4 +3863,7 @@ <!-- Toast message for background started foreground service while-in-use permission restriction feature --> <java-symbol type="string" name="allow_while_in_use_permission_in_fgs" /> + + <!-- Whether to expand the lock screen user switcher by default --> + <java-symbol type="bool" name="config_expandLockScreenUserSwitcher" /> </resources> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index ee93b397bedf..59335a595334 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -111,6 +111,10 @@ <uses-permission android:name="android.permission.MOVE_PACKAGE" /> <uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" /> + <!-- gating and logging permissions --> + <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" /> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> + <!-- os storage test permissions --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.ASEC_ACCESS" /> diff --git a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java index bf782034c8f1..7733559c156a 100644 --- a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java +++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java @@ -90,18 +90,18 @@ public class AtomicFormulaTest { } @Test - public void testValidAtomicFormula_stringValue_appCertificateAutoHashed() { + public void testValidAtomicFormula_stringValue_appCertificateIsNotAutoHashed() { String appCert = "cert"; StringAtomicFormula stringAtomicFormula = new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, appCert); assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE); - assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCert); - assertThat(stringAtomicFormula.getIsHashedValue()).isTrue(); + assertThat(stringAtomicFormula.getValue()).matches(appCert); + assertThat(stringAtomicFormula.getIsHashedValue()).isFalse(); } @Test - public void testValidAtomicFormula_stringValue_installerCertificateAutoHashed() { + public void testValidAtomicFormula_stringValue_installerCertificateIsNotAutoHashed() { String installerCert = "cert"; StringAtomicFormula stringAtomicFormula = new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE, @@ -109,8 +109,8 @@ public class AtomicFormulaTest { assertThat(stringAtomicFormula.getKey()).isEqualTo( AtomicFormula.INSTALLER_CERTIFICATE); - assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCert); - assertThat(stringAtomicFormula.getIsHashedValue()).isTrue(); + assertThat(stringAtomicFormula.getValue()).matches(installerCert); + assertThat(stringAtomicFormula.getIsHashedValue()).isFalse(); } @Test diff --git a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java index c1806028f75b..dc03167f51a9 100644 --- a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java +++ b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java @@ -40,7 +40,7 @@ public class IntegrityFormulaTest { assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME); assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName); - assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false); + assertThat(stringAtomicFormula.getIsHashedValue()).isFalse(); } @Test @@ -53,8 +53,8 @@ public class IntegrityFormulaTest { (AtomicFormula.StringAtomicFormula) formula; assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE); - assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCertificate); - assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true); + assertThat(stringAtomicFormula.getValue()).matches(appCertificate); + assertThat(stringAtomicFormula.getIsHashedValue()).isFalse(); } @Test @@ -68,7 +68,7 @@ public class IntegrityFormulaTest { assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME); assertThat(stringAtomicFormula.getValue()).isEqualTo(installerName); - assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false); + assertThat(stringAtomicFormula.getIsHashedValue()).isFalse(); } @Test @@ -81,8 +81,8 @@ public class IntegrityFormulaTest { (AtomicFormula.StringAtomicFormula) formula; assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_CERTIFICATE); - assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCertificate); - assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true); + assertThat(stringAtomicFormula.getValue()).matches(installerCertificate); + assertThat(stringAtomicFormula.getIsHashedValue()).isFalse(); } @Test diff --git a/core/tests/coretests/src/android/os/BuildTest.java b/core/tests/coretests/src/android/os/BuildTest.java index decc76869a53..2295eb989108 100644 --- a/core/tests/coretests/src/android/os/BuildTest.java +++ b/core/tests/coretests/src/android/os/BuildTest.java @@ -60,7 +60,7 @@ public class BuildTest extends TestCase { assertNotEmpty("BRAND", Build.BRAND); assertNotEmpty("MODEL", Build.MODEL); assertNotEmpty("VERSION.INCREMENTAL", Build.VERSION.INCREMENTAL); - assertNotEmpty("VERSION.RELEASE", Build.VERSION.RELEASE); + assertNotEmpty("VERSION.RELEASE", Build.VERSION.RELEASE_OR_CODENAME); assertNotEmpty("TYPE", Build.TYPE); Assert.assertNotNull("TAGS", Build.TAGS); // TAGS is allowed to be empty. assertNotEmpty("FINGERPRINT", Build.FINGERPRINT); diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index df6b9066ea5c..ce71bebfc455 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -38,6 +38,7 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -355,6 +356,7 @@ public class ChooserActivityTest { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; + markWorkProfileUserAvailable(); Intent sendIntent = createSendTextIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTestWithOtherProfile(2); @@ -1209,17 +1211,24 @@ public class ChooserActivityTest { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; int personalProfileTargets = 3; + int otherProfileTargets = 1; List<ResolvedComponentInfo> personalResolvedComponentInfos = - createResolvedComponentsForTest(personalProfileTargets); + createResolvedComponentsForTestWithOtherProfile( + personalProfileTargets + otherProfileTargets, /* userID */ 10); int workProfileTargets = 4; List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest( workProfileTargets); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos); + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos); + Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent sendIntent = createSendTextIntent(); sendIntent.setType("TestType"); markWorkProfileUserAvailable(); @@ -1229,8 +1238,6 @@ public class ChooserActivityTest { waitForIdle(); assertThat(activity.getCurrentUserHandle().getIdentifier(), is(0)); - // The work list adapter must only be filled when we open the work tab - assertThat(activity.getWorkListAdapter().getCount(), is(0)); onView(withText(R.string.resolver_work_tab)).perform(click()); assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10)); assertThat(activity.getPersonalListAdapter().getCount(), is(personalProfileTargets)); @@ -1243,11 +1250,22 @@ public class ChooserActivityTest { ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); int workProfileTargets = 4; + List<ResolvedComponentInfo> personalResolvedComponentInfos = + createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(workProfileTargets); + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent sendIntent = createSendTextIntent(); sendIntent.setType("TestType"); @@ -1357,6 +1375,20 @@ public class ChooserActivityTest { return infoList; } + private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile( + int numberOfResults, int userId) { + List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults); + for (int i = 0; i < numberOfResults; i++) { + if (i == 0) { + infoList.add( + ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId)); + } else { + infoList.add(ResolverDataProvider.createResolvedComponentInfo(i)); + } + } + return infoList; + } + private List<ResolvedComponentInfo> createResolvedComponentsForTestWithUserId( int numberOfResults, int userId) { List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults); diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java index eee62bb791bf..a68b59086d42 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java @@ -16,10 +16,15 @@ package com.android.internal.app; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.annotation.Nullable; +import android.app.prediction.AppPredictionContext; +import android.app.prediction.AppPredictionManager; +import android.app.prediction.AppPredictor; import android.app.usage.UsageStatsManager; import android.content.ContentResolver; import android.content.Context; @@ -40,6 +45,8 @@ import com.android.internal.app.chooser.TargetInfo; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import org.mockito.Mockito; + import java.util.function.Function; public class ChooserWrapperActivity extends ChooserActivity { @@ -173,6 +180,12 @@ public class ChooserWrapperActivity extends ChooserActivity { return mMultiProfilePagerAdapter.getCurrentUserHandle(); } + @Override + public Context createContextAsUser(UserHandle user, int flags) { + // return the current context as a work profile doesn't really exist in these tests + return getApplicationContext(); + } + /** * We cannot directly mock the activity created since instrumentation creates it. * <p> diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java index 911490f30799..5f4194aa51e3 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java @@ -225,6 +225,7 @@ public class ResolverActivityTest { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; + markWorkProfileUserAvailable(); Intent sendIntent = createSendImageIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTestWithOtherProfile(2); @@ -246,7 +247,6 @@ public class ResolverActivityTest { chosen[0] = targetInfo.getResolveInfo(); return true; }; - // Make a stable copy of the components as the original list may be modified List<ResolvedComponentInfo> stableCopy = createResolvedComponentsForTestWithOtherProfile(2); @@ -443,7 +443,7 @@ public class ResolverActivityTest { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; List<ResolvedComponentInfo> personalResolvedComponentInfos = - createResolvedComponentsForTest(3); + createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), @@ -451,6 +451,11 @@ public class ResolverActivityTest { when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent sendIntent = createSendImageIntent(); markWorkProfileUserAvailable(); @@ -478,17 +483,20 @@ public class ResolverActivityTest { Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class), - eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + eq(sOverrides.workProfileUserHandle))) + .thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class), - eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + eq(sOverrides.workProfileUserHandle))) + .thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class), @@ -502,7 +510,7 @@ public class ResolverActivityTest { onView(withText(R.string.resolver_work_tab)).perform(click()); assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10)); - assertThat(activity.getPersonalListAdapter().getCount(), is(3)); + assertThat(activity.getPersonalListAdapter().getCount(), is(2)); } @Test @@ -511,14 +519,20 @@ public class ResolverActivityTest { ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); List<ResolvedComponentInfo> personalResolvedComponentInfos = - createResolvedComponentsForTest(3); + createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos); + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent sendIntent = createSendImageIntent(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); @@ -536,14 +550,20 @@ public class ResolverActivityTest { ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); List<ResolvedComponentInfo> personalResolvedComponentInfos = - createResolvedComponentsForTest(3); + createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos); + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); Intent sendIntent = createSendImageIntent(); ResolveInfo[] chosen = new ResolveInfo[1]; sOverrides.onSafelyStartCallback = targetInfo -> { @@ -587,17 +607,20 @@ public class ResolverActivityTest { Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class), - eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + eq(sOverrides.workProfileUserHandle))) + .thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class), - eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + eq(sOverrides.workProfileUserHandle))) + .thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + Mockito.isA(List.class))) + .thenReturn(new ArrayList<>(personalResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class), @@ -678,6 +701,20 @@ public class ResolverActivityTest { return infoList; } + private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile( + int numberOfResults, int userId) { + List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults); + for (int i = 0; i < numberOfResults; i++) { + if (i == 0) { + infoList.add( + ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId)); + } else { + infoList.add(ResolverDataProvider.createResolvedComponentInfo(i)); + } + } + return infoList; + } + private void waitForIdle() { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml index a200a510cf12..fe1182ecad4f 100644 --- a/data/etc/com.android.settings.xml +++ b/data/etc/com.android.settings.xml @@ -26,6 +26,7 @@ <permission name="android.permission.DELETE_PACKAGES"/> <permission name="android.permission.FORCE_STOP_PACKAGES"/> <permission name="android.permission.LOCAL_MAC_ADDRESS"/> + <permission name="android.permission.LOG_COMPAT_CHANGE" /> <permission name="android.permission.MANAGE_DEBUGGING"/> <permission name="android.permission.MANAGE_DEVICE_ADMINS"/> <permission name="android.permission.MANAGE_FINGERPRINT"/> @@ -37,8 +38,10 @@ <permission name="android.permission.MODIFY_PHONE_STATE"/> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <permission name="android.permission.MOVE_PACKAGE"/> + <permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" /> <permission name="android.permission.OVERRIDE_WIFI_CONFIG"/> <permission name="android.permission.PACKAGE_USAGE_STATS"/> + <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> <permission name="android.permission.READ_SEARCH_INDEXABLES"/> <permission name="android.permission.REBOOT"/> diff --git a/data/etc/platform.xml b/data/etc/platform.xml index da505505628e..6929d0d1879d 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -72,6 +72,11 @@ <group gid="net_admin" /> </permission> + <permission name="android.permission.MAINLINE_NETWORK_STACK" > + <group gid="net_admin" /> + <group gid="net_raw" /> + </permission> + <!-- The group that /cache belongs to, linked to the permission set on the applications that can access /cache --> <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" > diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index b5eba090691f..b9a7e225bdb9 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -366,6 +366,10 @@ applications that come with the platform <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/> <!-- Permission required for Tethering CTS tests. --> <permission name="android.permission.TETHER_PRIVILEGED"/> + <!-- Permissions required for ganting and logging --> + <permission name="android.permission.LOG_COMPAT_CHANGE" /> + <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> + <permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" /> <!-- Permissions required to test ambient display. --> <permission name="android.permission.READ_DREAM_STATE" /> <permission name="android.permission.WRITE_DREAM_STATE" /> diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp index 3681c69e912b..a3d552faeb0a 100644 --- a/libs/hwui/HardwareBitmapUploader.cpp +++ b/libs/hwui/HardwareBitmapUploader.cpp @@ -187,7 +187,9 @@ private: EGLSyncKHR fence = mUploadThread->queue().runSync([&]() -> EGLSyncKHR { AutoSkiaGlTexture glTexture; glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image); - GL_CHECKPOINT(MODERATE); + if (GLUtils::dumpGLErrors()) { + return EGL_NO_SYNC_KHR; + } // glTexSubImage2D is synchronous in sense that it memcpy() from pointer that we // provide. @@ -195,19 +197,26 @@ private: // when we first use it in drawing glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), format.format, format.type, bitmap.getPixels()); - GL_CHECKPOINT(MODERATE); + if (GLUtils::dumpGLErrors()) { + return EGL_NO_SYNC_KHR; + } EGLSyncKHR uploadFence = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_FENCE_KHR, NULL); - LOG_ALWAYS_FATAL_IF(uploadFence == EGL_NO_SYNC_KHR, - "Could not create sync fence %#x", eglGetError()); + if (uploadFence == EGL_NO_SYNC_KHR) { + ALOGW("Could not create sync fence %#x", eglGetError()); + }; glFlush(); + GLUtils::dumpGLErrors(); return uploadFence; }); + if (fence == EGL_NO_SYNC_KHR) { + return false; + } EGLint waitStatus = eglClientWaitSyncKHR(display, fence, 0, FENCE_TIMEOUT); - LOG_ALWAYS_FATAL_IF(waitStatus != EGL_CONDITION_SATISFIED_KHR, - "Failed to wait for the fence %#x", eglGetError()); + ALOGE_IF(waitStatus != EGL_CONDITION_SATISFIED_KHR, + "Failed to wait for the fence %#x", eglGetError()); eglDestroySyncKHR(display, fence); } diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl index 194669c19018..9131f3bc960d 100644 --- a/media/java/android/media/IMediaRoute2Provider.aidl +++ b/media/java/android/media/IMediaRoute2Provider.aidl @@ -37,5 +37,4 @@ oneway interface IMediaRoute2Provider { void notifyControlRequestSent(String id, in Intent request); void requestSetVolume(String id, int volume); - void requestUpdateVolume(String id, int delta); } diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index dac0fba876be..6fef46889742 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -52,7 +52,6 @@ interface IMediaRouterService { void sendControlRequest(IMediaRouter2Client client, in MediaRoute2Info route, in Intent request); void requestSetVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int volume); - void requestUpdateVolume2(IMediaRouter2Client client, in MediaRoute2Info route, int direction); void requestCreateSession(IMediaRouter2Client client, in MediaRoute2Info route, int requestId, in @nullable Bundle sessionHints); @@ -70,8 +69,6 @@ interface IMediaRouterService { void requestSetVolume2Manager(IMediaRouter2Manager manager, in MediaRoute2Info route, int volume); - void requestUpdateVolume2Manager(IMediaRouter2Manager manager, - in MediaRoute2Info route, int direction); List<RoutingSessionInfo> getActiveSessions(IMediaRouter2Manager manager); void selectClientRoute(IMediaRouter2Manager manager, diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index d0b5d486d19c..20a59bba54c6 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -46,13 +46,20 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * Base class for media route provider services. * <p> + * Media route provider services are used to publish {@link MediaRoute2Info media routes} such as + * speakers, TVs, etc. The routes are published by calling {@link #notifyRoutes(Collection)}. + * Media apps which use {@link MediaRouter2} can request to play their media on the routes. + * </p><p> + * When {@link MediaRouter2 media router} wants to play media on a route, + * {@link #onCreateSession(String, String, long, Bundle)} will be called to handle the request. + * A session can be considered as a group of currently selected routes for each connection. + * Create and manage the sessions by yourself, and notify the {@link RoutingSessionInfo + * session infos} when there are any changes. + * </p><p> * The system media router service will bind to media route provider services when a * {@link RouteDiscoveryPreference discovery preference} is registered via - * a {@link MediaRouter2 media router} by an application. - * </p><p> - * To implement your own media route provider service, extend this class and - * override {@link #onDiscoveryPreferenceChanged(RouteDiscoveryPreference)} to publish - * {@link MediaRoute2Info routes}. + * a {@link MediaRouter2 media router} by an application. See + * {@link #onDiscoveryPreferenceChanged(RouteDiscoveryPreference)} for the details. * </p> */ public abstract class MediaRoute2ProviderService extends Service { @@ -118,22 +125,15 @@ public abstract class MediaRoute2ProviderService extends Service { public abstract void onControlRequest(@NonNull String routeId, @NonNull Intent request); /** - * Called when requestSetVolume is called on a route of the provider + * Called when requestSetVolume is called on a route of the provider. * * @param routeId the id of the route * @param volume the target volume + * @see MediaRoute2Info#getVolumeMax() */ public abstract void onSetVolume(@NonNull String routeId, int volume); /** - * Called when requestUpdateVolume is called on a route of the provider - * - * @param routeId id of the route - * @param delta the delta to add to the current volume - */ - public abstract void onUpdateVolume(@NonNull String routeId, int delta); - - /** * Gets information of the session with the given id. * * @param sessionId id of the session @@ -520,14 +520,5 @@ public abstract class MediaRoute2ProviderService extends Service { mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetVolume, MediaRoute2ProviderService.this, routeId, volume)); } - - @Override - public void requestUpdateVolume(String routeId, int delta) { - if (!checkCallerisSystem()) { - return; - } - mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUpdateVolume, - MediaRoute2ProviderService.this, routeId, delta)); - } } } diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 515cabe5a5c9..d7b74df0a5e6 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -462,31 +462,6 @@ public class MediaRouter2 { } } - /** - * Requests an incremental volume update for the route asynchronously. - * <p> - * It may have no effect if the route is currently not selected. - * </p> - * - * @param delta The delta to add to the current volume. - * @hide - */ - public void requestUpdateVolume(@NonNull MediaRoute2Info route, int delta) { - Objects.requireNonNull(route, "route must not be null"); - - Client2 client; - synchronized (sRouterLock) { - client = mClient; - } - if (client != null) { - try { - mMediaRouterService.requestUpdateVolume2(client, route, delta); - } catch (RemoteException ex) { - Log.e(TAG, "Unable to send control request.", ex); - } - } - } - void addRoutesOnHandler(List<MediaRoute2Info> routes) { // TODO: When onRoutesAdded is first called, // 1) clear mRoutes before adding the routes diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 662eeb1418f1..b1f930d0f2cc 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -294,30 +294,6 @@ public class MediaRouter2Manager { } } - /** - * Requests an incremental volume update for the route asynchronously. - * <p> - * It may have no effect if the route is currently not selected. - * </p> - * - * @param delta The delta to add to the current volume. - */ - public void requestUpdateVolume(@NonNull MediaRoute2Info route, int delta) { - Objects.requireNonNull(route, "route must not be null"); - - Client client; - synchronized (sLock) { - client = mClient; - } - if (client != null) { - try { - mMediaRouterService.requestUpdateVolume2Manager(client, route, delta); - } catch (RemoteException ex) { - Log.e(TAG, "Unable to send control request.", ex); - } - } - } - void addRoutesOnHandler(List<MediaRoute2Info> routes) { synchronized (mRoutesLock) { for (MediaRoute2Info route : routes) { diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java index 4316e42bb0e1..f10e5ebb5d3e 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java @@ -289,12 +289,13 @@ public class MediaRouterManagerTest { MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME); int originalVolume = volRoute.getVolume(); - int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1); + int targetVolume = originalVolume == volRoute.getVolumeMax() + ? originalVolume - 1 : originalVolume + 1; awaitOnRouteChangedManager( - () -> mManager.requestUpdateVolume(volRoute, deltaVolume), + () -> mManager.requestSetVolume(volRoute, targetVolume), ROUTE_ID_VARIABLE_VOLUME, - (route -> route.getVolume() == originalVolume + deltaVolume)); + (route -> route.getVolume() == targetVolume)); awaitOnRouteChangedManager( () -> mManager.requestSetVolume(volRoute, originalVolume), diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java index f1a08f29e0cc..1a866cafff90 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java @@ -154,20 +154,6 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onUpdateVolume(String routeId, int delta) { - MediaRoute2Info route = mRoutes.get(routeId); - if (route == null) { - return; - } - int volume = route.getVolume() + delta; - volume = Math.min(volume, Math.max(0, route.getVolumeMax())); - mRoutes.put(routeId, new MediaRoute2Info.Builder(route) - .setVolume(volume) - .build()); - publishRoutes(); - } - - @Override public void onCreateSession(String packageName, String routeId, long requestId, @Nullable Bundle sessionHints) { MediaRoute2Info route = mRoutes.get(routeId); diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index 9c8345dafbc8..62124934f416 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -10,6 +10,7 @@ android_library { "androidx.appcompat_appcompat", "androidx.lifecycle_lifecycle-runtime", "androidx.mediarouter_mediarouter-nodeps", + "iconloader", "SettingsLibHelpUtils", "SettingsLibRestrictedLockUtils", diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index de523d9f9bc8..213e3657254d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -3,6 +3,7 @@ package com.android.settingslib; import android.annotation.ColorInt; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -13,6 +14,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.location.LocationManager; import android.media.AudioManager; @@ -27,8 +29,11 @@ import android.telephony.AccessNetworkConstants; import android.telephony.NetworkRegistrationInfo; import android.telephony.ServiceState; +import androidx.annotation.NonNull; + import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.UserIcons; +import com.android.launcher3.icons.IconFactory; import com.android.settingslib.drawable.UserIconDrawable; import java.text.NumberFormat; @@ -424,6 +429,19 @@ public class Utils { return state; } + /** + * Get the {@link Drawable} that represents the app icon + */ + public static @NonNull Drawable getBadgedIcon( + @NonNull Context context, @NonNull ApplicationInfo appInfo) { + final UserHandle user = UserHandle.getUserHandleForUid(appInfo.uid); + try (IconFactory iconFactory = IconFactory.obtain(context)) { + final Bitmap iconBmp = iconFactory.createBadgedIconBitmap( + appInfo.loadUnbadgedIcon(context.getPackageManager()), user, false).icon; + return new BitmapDrawable(context.getResources(), iconBmp); + } + } + private static boolean isNotInIwlan(ServiceState serviceState) { final NetworkRegistrationInfo networkRegWlan = serviceState.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index 19c666459723..af728887c917 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -59,6 +59,7 @@ import androidx.lifecycle.OnLifecycleEvent; import com.android.internal.R; import com.android.internal.util.ArrayUtils; +import com.android.settingslib.Utils; import java.io.File; import java.io.IOException; @@ -495,7 +496,7 @@ public class ApplicationsState { return; } synchronized (entry) { - entry.ensureIconLocked(mContext, mDrawableFactory); + entry.ensureIconLocked(mContext); } } @@ -1216,7 +1217,7 @@ public class ApplicationsState { AppEntry entry = mAppEntries.get(i); if (entry.icon == null || !entry.mounted) { synchronized (entry) { - if (entry.ensureIconLocked(mContext, mDrawableFactory)) { + if (entry.ensureIconLocked(mContext)) { if (!mRunning) { mRunning = true; Message m = mMainHandler.obtainMessage( @@ -1587,10 +1588,10 @@ public class ApplicationsState { } } - boolean ensureIconLocked(Context context, IconDrawableFactory drawableFactory) { + boolean ensureIconLocked(Context context) { if (this.icon == null) { if (this.apkFile.exists()) { - this.icon = drawableFactory.getBadgedIcon(info); + this.icon = Utils.getBadgedIcon(context, info); return true; } else { this.mounted = false; @@ -1601,7 +1602,7 @@ public class ApplicationsState { // its icon. if (this.apkFile.exists()) { this.mounted = true; - this.icon = drawableFactory.getBadgedIcon(info); + this.icon = Utils.getBadgedIcon(context, info); return true; } } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 6a89b71be897..1d679c7bcbdd 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -223,6 +223,11 @@ <!-- permissions required for CTS test - PhoneStateListenerTest --> <uses-permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH" /> + <!-- Permissions required for ganting and logging --> + <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> + <uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"/> + <!-- Permission required for CTS test - UiModeManagerTest --> <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 139a8c3f7411..1fe967b4750d 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -645,7 +645,6 @@ <activity android:name=".controls.management.ControlsProviderSelectorActivity" android:label="Controls Providers" android:theme="@style/Theme.ControlsManagement" - android:exported="true" android:showForAllUsers="true" android:excludeFromRecents="true" android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden" diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml index a1c593fa455c..b14bc7de06c4 100644 --- a/packages/SystemUI/res/layout/auth_credential_password_view.xml +++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml @@ -73,6 +73,7 @@ android:layout_width="208dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" + android:minHeight="48dp" android:gravity="center" android:inputType="textPassword" android:maxLength="500" diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 6062a3d45be0..20d19ece575c 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -533,10 +533,6 @@ public class BubbleStackView extends FrameLayout { mBubbleContainer.addView(mOverflowBtn, 0, new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); - mOverflowBtn.setOnClickListener(v -> { - setSelectedBubble(null); - }); - TypedArray ta = mContext.obtainStyledAttributes( new int[]{android.R.attr.colorBackgroundFloating}); int bgColor = ta.getColor(0, Color.WHITE /* default */); @@ -856,6 +852,10 @@ public class BubbleStackView extends FrameLayout { updateBubbleZOrdersAndDotPosition(false /* animate */); } + void showOverflow() { + setSelectedBubble(null); + } + /** * Changes the currently selected bubble. If the stack is already expanded, the newly selected * bubble will be shown immediately. This does not change the expanded state or change the @@ -950,6 +950,10 @@ public class BubbleStackView extends FrameLayout { } if (mIsExpanded) { if (isIntersecting(mBubbleContainer, x, y)) { + if (BubbleExperimentConfig.allowBubbleOverflow(mContext) + && isIntersecting(mOverflowBtn, x, y)) { + return mOverflowBtn; + } // Could be tapping or dragging a bubble while expanded for (int i = 0; i < getBubbleCount(); i++) { BadgedImageView view = (BadgedImageView) mBubbleContainer.getChildAt(i); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java index fdeaf1f016c3..5a9d44b6da2c 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java @@ -24,6 +24,7 @@ import android.view.View; import android.view.ViewConfiguration; import com.android.systemui.Dependency; +import com.android.systemui.R; /** * Handles interpreting touches on a {@link BubbleStackView}. This includes expanding, collapsing, @@ -109,6 +110,10 @@ class BubbleTouchHandler implements View.OnTouchListener { if (!(mTouchedView instanceof BadgedImageView) && !(mTouchedView instanceof BubbleStackView) && !(mTouchedView instanceof BubbleFlyoutView)) { + + if (mTouchedView.getId() == R.id.bubble_overflow_button) { + mStack.showOverflow(); + } // Not touching anything touchable, but we shouldn't collapse (e.g. touching edge // of expanded view). mStack.hideBubbleMenu(); diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index a6f1d84877c5..7de1557ebc65 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -19,9 +19,12 @@ package com.android.systemui.controls.controller import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.ComponentName +import android.content.ContentResolver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.database.ContentObserver +import android.net.Uri import android.os.Environment import android.os.UserHandle import android.provider.Settings @@ -30,6 +33,7 @@ import android.service.controls.actions.ControlAction import android.util.ArrayMap import android.util.Log import com.android.internal.annotations.GuardedBy +import com.android.internal.annotations.VisibleForTesting import com.android.systemui.DumpController import com.android.systemui.Dumpable import com.android.systemui.broadcast.BroadcastDispatcher @@ -53,15 +57,16 @@ class ControlsControllerImpl @Inject constructor ( private val uiController: ControlsUiController, private val bindingController: ControlsBindingController, private val listingController: ControlsListingController, - broadcastDispatcher: BroadcastDispatcher, + private val broadcastDispatcher: BroadcastDispatcher, optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>, dumpController: DumpController ) : Dumpable, ControlsController { companion object { private const val TAG = "ControlsControllerImpl" - const val CONTROLS_AVAILABLE = "systemui.controls_available" - const val USER_CHANGE_RETRY_DELAY = 500L // ms + internal const val CONTROLS_AVAILABLE = "systemui.controls_available" + internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE) + private const val USER_CHANGE_RETRY_DELAY = 500L // ms } // Map of map: ComponentName -> (String -> ControlInfo). @@ -69,9 +74,11 @@ class ControlsControllerImpl @Inject constructor ( @GuardedBy("currentFavorites") private val currentFavorites = ArrayMap<ComponentName, MutableMap<String, ControlInfo>>() - private var userChanging = true - override var available = Settings.Secure.getInt( - context.contentResolver, CONTROLS_AVAILABLE, 0) != 0 + private var userChanging: Boolean = true + + private val contentResolver: ContentResolver + get() = context.contentResolver + override var available = Settings.Secure.getInt(contentResolver, CONTROLS_AVAILABLE, 0) != 0 private set private var currentUser = context.user @@ -95,8 +102,8 @@ class ControlsControllerImpl @Inject constructor ( val fileName = Environment.buildPath( userContext.filesDir, ControlsFavoritePersistenceWrapper.FILE_NAME) persistenceWrapper.changeFile(fileName) - available = Settings.Secure.getIntForUser( - context.contentResolver, CONTROLS_AVAILABLE, 0) != 0 + available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE, + /* default */ 0, newUser.identifier) != 0 synchronized(currentFavorites) { currentFavorites.clear() } @@ -123,6 +130,25 @@ class ControlsControllerImpl @Inject constructor ( } } + @VisibleForTesting + internal val settingObserver = object : ContentObserver(null) { + override fun onChange(selfChange: Boolean, uri: Uri, userId: Int) { + // Do not listen to changes in the middle of user change, those will be read by the + // user-switch receiver. + if (userChanging || userId != currentUserId) { + return + } + available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE, + /* default */ 0, currentUserId) != 0 + synchronized(currentFavorites) { + currentFavorites.clear() + } + if (available) { + loadFavorites() + } + } + } + init { dumpController.registerDumpable(this) if (available) { @@ -135,6 +161,7 @@ class ControlsControllerImpl @Inject constructor ( executor, UserHandle.ALL ) + contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL) } private fun confirmAvailability(): Boolean { diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index fad2d94d6cf3..88b19b58a453 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -34,14 +34,17 @@ import android.widget.ImageView import android.widget.TextView import com.android.systemui.controls.controller.ControlsController +import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.R const val MIN_LEVEL = 0 const val MAX_LEVEL = 10000 +private const val UPDATE_DELAY_IN_MILLIS = 2000L class ControlViewHolder( val layout: ViewGroup, - val controlsController: ControlsController + val controlsController: ControlsController, + val uiExecutor: DelayableExecutor ) { val icon: ImageView = layout.requireViewById(R.id.icon) val status: TextView = layout.requireViewById(R.id.status) @@ -52,6 +55,7 @@ class ControlViewHolder( val clipLayer: ClipDrawable val gd: GradientDrawable lateinit var cws: ControlWithState + var cancelUpdate: Runnable? = null init { val ld = layout.getBackground() as LayerDrawable @@ -63,6 +67,8 @@ class ControlViewHolder( fun bindData(cws: ControlWithState) { this.cws = cws + cancelUpdate?.run() + val (status, template) = cws.control?.let { title.setText(it.getTitle()) subtitle.setText(it.getSubtitle()) @@ -86,6 +92,27 @@ class ControlViewHolder( findBehavior(status, template).apply(this, cws) } + fun actionResponse(@ControlAction.ResponseResult response: Int) { + val text = when (response) { + ControlAction.RESPONSE_OK -> "Success" + ControlAction.RESPONSE_FAIL -> "Error" + else -> "" + } + + if (!text.isEmpty()) { + val previousText = status.getText() + val previousTextExtra = statusExtra.getText() + + cancelUpdate = uiExecutor.executeDelayed({ + status.setText(previousText) + statusExtra.setText(previousTextExtra) + }, UPDATE_DELAY_IN_MILLIS) + + status.setText(text) + statusExtra.setText("") + } + } + fun action(action: ControlAction) { controlsController.action(cws.ci, action) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt index b07a75d5e757..d70c86fc3266 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt @@ -22,6 +22,8 @@ import android.service.controls.actions.ControlAction import android.view.ViewGroup interface ControlsUiController { + val available: Boolean + fun show(parent: ViewGroup) fun hide() fun onRefreshState(componentName: ComponentName, controls: List<Control>) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index a777faf57fce..ed521e3be535 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -38,10 +38,10 @@ import com.android.systemui.controls.controller.ControlInfo import com.android.systemui.controls.management.ControlsProviderSelectorActivity import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.R +import com.android.systemui.util.concurrency.DelayableExecutor import dagger.Lazy -import java.util.concurrent.Executor import javax.inject.Inject import javax.inject.Singleton @@ -104,18 +104,23 @@ class TokenProviderConnection(val cc: ControlsController, val context: Context) } } +private data class ControlKey(val componentName: ComponentName, val controlId: String) + @Singleton class ControlsUiControllerImpl @Inject constructor ( val controlsController: Lazy<ControlsController>, val context: Context, - @Main val uiExecutor: Executor + @Main val uiExecutor: DelayableExecutor ) : ControlsUiController { private lateinit var controlInfos: List<ControlInfo> - private val controlsById = mutableMapOf<Pair<ComponentName, String>, ControlWithState>() - private val controlViewsById = mutableMapOf<String, ControlViewHolder>() + private val controlsById = mutableMapOf<ControlKey, ControlWithState>() + private val controlViewsById = mutableMapOf<ControlKey, ControlViewHolder>() private lateinit var parent: ViewGroup + override val available: Boolean + get() = controlsController.get().available + override fun show(parent: ViewGroup) { Log.d(TAG, "show()") @@ -125,7 +130,7 @@ class ControlsUiControllerImpl @Inject constructor ( controlInfos.map { ControlWithState(it, null) - }.associateByTo(controlsById) { Pair(it.ci.component, it.ci.controlId) } + }.associateByTo(controlsById) { ControlKey(it.ci.component, it.ci.controlId) } if (controlInfos.isEmpty()) { showInitialSetupView() @@ -178,9 +183,10 @@ class ControlsUiControllerImpl @Inject constructor ( val item = inflater.inflate( R.layout.controls_base_item, lastRow, false) as ViewGroup lastRow.addView(item) - val cvh = ControlViewHolder(item, controlsController.get()) - cvh.bindData(controlsById.get(Pair(it.component, it.controlId))!!) - controlViewsById.put(it.controlId, cvh) + val cvh = ControlViewHolder(item, controlsController.get(), uiExecutor) + val key = ControlKey(it.component, it.controlId) + cvh.bindData(controlsById.getValue(key)) + controlViewsById.put(key, cvh) } if ((controlInfos.size % 2) == 1) { @@ -205,21 +211,24 @@ class ControlsUiControllerImpl @Inject constructor ( override fun onRefreshState(componentName: ComponentName, controls: List<Control>) { Log.d(TAG, "onRefreshState()") controls.forEach { c -> - controlsById.get(Pair(componentName, c.getControlId()))?.let { + controlsById.get(ControlKey(componentName, c.getControlId()))?.let { Log.d(TAG, "onRefreshState() for id: " + c.getControlId()) val cws = ControlWithState(it.ci, c) - controlsById.put(Pair(componentName, c.getControlId()), cws) + val key = ControlKey(componentName, c.getControlId()) + controlsById.put(key, cws) uiExecutor.execute { - controlViewsById.get(c.getControlId())?.bindData(cws) + controlViewsById.get(key)?.bindData(cws) } } } } override fun onActionResponse(componentName: ComponentName, controlId: String, response: Int) { - Log.d(TAG, "onActionResponse()") - TODO("not implemented") + val key = ControlKey(componentName, controlId) + uiExecutor.execute { + controlViewsById.get(key)?.actionResponse(response) + } } private fun createRow(inflater: LayoutInflater, parent: ViewGroup): ViewGroup { diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 45c07a3e4693..082b0656b32e 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -1899,9 +1899,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } private boolean shouldShowControls() { - return isCurrentUserOwner() - && !mKeyguardManager.isDeviceLocked() - && Settings.Secure.getInt(mContext.getContentResolver(), - "systemui.controls_available", 0) == 1; + return !mKeyguardManager.isDeviceLocked() + && mControlsUiController.getAvailable(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java index 0134aa3a15df..5de6d1c42b4f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java @@ -169,7 +169,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)) { v.setText(mContext.getString( com.android.internal.R.string.bugreport_status, - Build.VERSION.RELEASE, + Build.VERSION.RELEASE_OR_CODENAME, Build.ID)); v.setVisibility(View.VISIBLE); } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java index 9e3e94ce4186..6c697184f082 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java @@ -36,6 +36,7 @@ import android.media.MediaMetadata; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; +import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -370,6 +371,13 @@ public class QSMediaPlayer { if (mSeamless == null) { return; } + Handler handler = mSeamless.getHandler(); + handler.post(() -> { + updateChipInternal(device); + }); + } + + private void updateChipInternal(MediaDevice device) { ColorStateList fgTintList = ColorStateList.valueOf(mForegroundColor); // Update the outline color diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 2907cd41a0db..8dfcb0ac215d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -134,6 +134,8 @@ public class UserSwitcherController implements Dumpable { mBroadcastDispatcher.registerReceiver( mReceiver, filter, null /* handler */, UserHandle.SYSTEM); + mSimpleUserSwitcher = shouldUseSimpleUserSwitcher(); + mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class); filter = new IntentFilter(); @@ -258,22 +260,20 @@ public class UserSwitcherController implements Dumpable { && mUserManager.canAddMoreUsers(); boolean createIsRestricted = !addUsersWhenLocked; - if (!mSimpleUserSwitcher) { - if (guestRecord == null) { - if (canCreateGuest) { - guestRecord = new UserRecord(null /* info */, null /* picture */, - true /* isGuest */, false /* isCurrent */, - false /* isAddUser */, createIsRestricted, canSwitchUsers); - checkIfAddUserDisallowedByAdminOnly(guestRecord); - records.add(guestRecord); - } - } else { - int index = guestRecord.isCurrent ? 0 : records.size(); - records.add(index, guestRecord); + if (guestRecord == null) { + if (canCreateGuest) { + guestRecord = new UserRecord(null /* info */, null /* picture */, + true /* isGuest */, false /* isCurrent */, + false /* isAddUser */, createIsRestricted, canSwitchUsers); + checkIfAddUserDisallowedByAdminOnly(guestRecord); + records.add(guestRecord); } + } else { + int index = guestRecord.isCurrent ? 0 : records.size(); + records.add(index, guestRecord); } - if (!mSimpleUserSwitcher && canCreateUser) { + if (canCreateUser) { UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */, false /* isGuest */, false /* isCurrent */, true /* isAddUser */, createIsRestricted, canSwitchUsers); @@ -562,8 +562,7 @@ public class UserSwitcherController implements Dumpable { private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) { public void onChange(boolean selfChange) { - mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(), - SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0; + mSimpleUserSwitcher = shouldUseSimpleUserSwitcher(); mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0; refreshUsers(UserHandle.USER_NULL); @@ -579,6 +578,7 @@ public class UserSwitcherController implements Dumpable { final UserRecord u = mUsers.get(i); pw.print(" "); pw.println(u.toString()); } + pw.println("mSimpleUserSwitcher=" + mSimpleUserSwitcher); } public String getCurrentUserName(Context context) { @@ -717,6 +717,13 @@ public class UserSwitcherController implements Dumpable { } } + private boolean shouldUseSimpleUserSwitcher() { + int defaultSimpleUserSwitcher = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_expandLockScreenUserSwitcher) ? 1 : 0; + return Settings.Global.getInt(mContext.getContentResolver(), + SIMPLE_USER_SWITCHER_GLOBAL_SETTING, defaultSimpleUserSwitcher) != 0; + } + public void startActivity(Intent intent) { mActivityStarter.startActivity(intent, true); } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java index a60ca6201419..49ada1a5e41e 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java @@ -158,7 +158,7 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference String demoTime = "1010"; // 10:10, a classic choice of horologists try { - String[] versionParts = android.os.Build.VERSION.RELEASE.split("\\."); + String[] versionParts = android.os.Build.VERSION.RELEASE_OR_CODENAME.split("\\."); int majorVersion = Integer.valueOf(versionParts[0]); demoTime = String.format("%02d00", majorVersion % 24); } catch (IllegalArgumentException ex) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt index 897091f69f36..e3bcdc8b0b60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt @@ -32,12 +32,13 @@ import androidx.test.filters.SmallTest import com.android.systemui.DumpController import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher -import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ControlStatus +import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -82,7 +83,7 @@ class ControlsControllerImplTest : SysuiTestCase() { private lateinit var broadcastReceiverCaptor: ArgumentCaptor<BroadcastReceiver> private lateinit var delayableExecutor: FakeExecutor - private lateinit var controller: ControlsController + private lateinit var controller: ControlsControllerImpl companion object { fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() @@ -416,5 +417,70 @@ class ControlsControllerImplTest : SysuiTestCase() { verify(listingController).changeUser(UserHandle.of(otherUser)) assertTrue(controller.getFavoriteControls().isEmpty()) assertEquals(otherUser, controller.currentUserId) + assertTrue(controller.available) + } + + @Test + fun testDisableFeature_notAvailable() { + Settings.Secure.putIntForUser(mContext.contentResolver, + ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user) + controller.settingObserver.onChange(false, ControlsControllerImpl.URI, 0) + assertFalse(controller.available) + } + + @Test + fun testDisableFeature_clearFavorites() { + controller.changeFavoriteStatus(TEST_CONTROL_INFO, true) + assertFalse(controller.getFavoriteControls().isEmpty()) + + Settings.Secure.putIntForUser(mContext.contentResolver, + ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user) + controller.settingObserver.onChange(false, ControlsControllerImpl.URI, user) + assertTrue(controller.getFavoriteControls().isEmpty()) + } + + @Test + fun testDisableFeature_noChangeForNotCurrentUser() { + controller.changeFavoriteStatus(TEST_CONTROL_INFO, true) + Settings.Secure.putIntForUser(mContext.contentResolver, + ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser) + controller.settingObserver.onChange(false, ControlsControllerImpl.URI, otherUser) + + assertTrue(controller.available) + assertFalse(controller.getFavoriteControls().isEmpty()) + } + + @Test + fun testCorrectUserSettingOnUserChange() { + Settings.Secure.putIntForUser(mContext.contentResolver, + ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser) + + val intent = Intent(Intent.ACTION_USER_SWITCHED).apply { + putExtra(Intent.EXTRA_USER_HANDLE, otherUser) + } + val pendingResult = mock(BroadcastReceiver.PendingResult::class.java) + `when`(pendingResult.sendingUserId).thenReturn(otherUser) + broadcastReceiverCaptor.value.pendingResult = pendingResult + + broadcastReceiverCaptor.value.onReceive(mContext, intent) + + assertFalse(controller.available) + } + + @Test + fun testCountFavoritesForComponent_singleComponent() { + controller.changeFavoriteStatus(TEST_CONTROL_INFO, true) + + assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT)) + assertEquals(0, controller.countFavoritesForComponent(TEST_COMPONENT_2)) + } + + @Test + fun testCountFavoritesForComponent_multipleComponents() { + controller.changeFavoriteStatus(TEST_CONTROL_INFO, true) + controller.changeFavoriteStatus(TEST_CONTROL_INFO_2, true) + + assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT)) + assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT_2)) } -}
\ No newline at end of file +} diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java index 07abe1adeb52..39c402be84a3 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -272,13 +272,6 @@ public class Tethering { mStateReceiver = new StateReceiver(); - mNetdCallback = new NetdCallback(); - try { - mNetd.registerUnsolicitedEventListener(mNetdCallback); - } catch (RemoteException e) { - mLog.e("Unable to register netd UnsolicitedEventListener"); - } - final UserManager userManager = (UserManager) mContext.getSystemService( Context.USER_SERVICE); mTetheringRestriction = new UserRestrictionActionListener(userManager, this); @@ -287,6 +280,14 @@ public class Tethering { // Load tethering configuration. updateConfiguration(); + // NetdCallback should be registered after updateConfiguration() to ensure + // TetheringConfiguration is created. + mNetdCallback = new NetdCallback(); + try { + mNetd.registerUnsolicitedEventListener(mNetdCallback); + } catch (RemoteException e) { + mLog.e("Unable to register netd UnsolicitedEventListener"); + } startStateMachineUpdaters(mHandler); startTrackDefaultNetwork(); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ec3dbe9f850e..672617090a71 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -6581,6 +6581,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private ArrayMap<NetworkRequestInfo, NetworkAgentInfo> computeRequestReassignmentForNetwork( + @NonNull final NetworkReassignment changes, @NonNull final NetworkAgentInfo newNetwork) { final int score = newNetwork.getCurrentScore(); final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = new ArrayMap<>(); @@ -6591,7 +6592,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // requests or not, and doesn't affect the network's score. if (nri.request.isListen()) continue; - final NetworkAgentInfo currentNetwork = nri.mSatisfier; + // The reassignment has been seeded with the initial assignment, therefore + // getReassignment can't be null and mNewNetwork is only null if there was no + // satisfier in the first place or there was an explicit reassignment to null. + final NetworkAgentInfo currentNetwork = changes.getReassignment(nri).mNewNetwork; final boolean satisfies = newNetwork.satisfies(nri.request); if (newNetwork == currentNetwork && satisfies) continue; @@ -6641,7 +6645,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (VDBG || DDBG) log("rematching " + newNetwork.name()); final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests = - computeRequestReassignmentForNetwork(newNetwork); + computeRequestReassignmentForNetwork(changes, newNetwork); // Find and migrate to this Network any NetworkRequests for // which this network is now the best. diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 2fc9d04623f8..c4e6427a0dfb 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -16,6 +16,11 @@ package com.android.server.compat; +import static android.Manifest.permission.LOG_COMPAT_CHANGE; +import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG; +import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import android.app.ActivityManager; import android.app.IActivityManager; import android.content.Context; @@ -67,12 +72,14 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChange(long changeId, ApplicationInfo appInfo) { + checkCompatChangeLogPermission(); reportChange(changeId, appInfo.uid, ChangeReporter.STATE_LOGGED); } @Override public void reportChangeByPackageName(long changeId, String packageName, int userId) { + checkCompatChangeLogPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return; @@ -82,11 +89,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChangeByUid(long changeId, int uid) { + checkCompatChangeLogPermission(); reportChange(changeId, uid, ChangeReporter.STATE_LOGGED); } @Override public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { + checkCompatChangeReadAndLogPermission(); if (mCompatConfig.isChangeEnabled(changeId, appInfo)) { reportChange(changeId, appInfo.uid, ChangeReporter.STATE_ENABLED); @@ -99,6 +108,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) { + checkCompatChangeReadAndLogPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return true; @@ -108,6 +118,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByUid(long changeId, int uid) { + checkCompatChangeReadAndLogPermission(); String[] packages = mContext.getPackageManager().getPackagesForUid(uid); if (packages == null || packages.length == 0) { return true; @@ -140,6 +151,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverrides(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); killPackage(packageName); } @@ -147,11 +159,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); } @Override public void clearOverrides(String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); killPackage(packageName); } @@ -159,12 +173,14 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void clearOverridesForTest(String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); } @Override public boolean clearOverride(long changeId, String packageName) throws RemoteException, SecurityException { + checkCompatChangeOverridePermission(); boolean existed = mCompatConfig.removeOverride(changeId, packageName); killPackage(packageName); return existed; @@ -172,11 +188,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { + checkCompatChangeReadAndLogPermission(); return mCompatConfig.getAppConfig(appInfo); } @Override public CompatibilityChangeInfo[] listAllChanges() { + checkCompatChangeReadPermission(); return mCompatConfig.dumpChanges(); } @@ -215,6 +233,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + checkCompatChangeReadAndLogPermission(); if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; mCompatConfig.dumpConfig(pw); } @@ -272,4 +291,30 @@ public class PlatformCompat extends IPlatformCompat.Stub { Binder.restoreCallingIdentity(identity); } } + + private void checkCompatChangeLogPermission() throws SecurityException { + if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE) + != PERMISSION_GRANTED) { + throw new SecurityException("Cannot log compat change usage"); + } + } + + private void checkCompatChangeReadPermission() throws SecurityException { + if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG) + != PERMISSION_GRANTED) { + throw new SecurityException("Cannot read compat change"); + } + } + + private void checkCompatChangeOverridePermission() throws SecurityException { + if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG) + != PERMISSION_GRANTED) { + throw new SecurityException("Cannot override compat change"); + } + } + + private void checkCompatChangeReadAndLogPermission() throws SecurityException { + checkCompatChangeReadPermission(); + checkCompatChangeLogPermission(); + } } diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java index 7b17b4ed6219..83588846ade8 100644 --- a/services/core/java/com/android/server/media/MediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java @@ -63,7 +63,6 @@ abstract class MediaRoute2Provider { public abstract void sendControlRequest(String routeId, Intent request); public abstract void requestSetVolume(String routeId, int volume); - public abstract void requestUpdateVolume(String routeId, int delta); @NonNull public String getUniqueId() { diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java index e22ea4681428..d08fb71d3dee 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java @@ -138,14 +138,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv } } - @Override - public void requestUpdateVolume(String routeId, int delta) { - if (mConnectionReady) { - mActiveConnection.requestUpdateVolume(routeId, delta); - updateBinding(); - } - } - public boolean hasComponentName(String packageName, String className) { return mComponentName.getPackageName().equals(packageName) && mComponentName.getClassName().equals(className); @@ -518,14 +510,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv } } - public void requestUpdateVolume(String routeId, int delta) { - try { - mProvider.requestUpdateVolume(routeId, delta); - } catch (RemoteException ex) { - Slog.e(TAG, "Failed to deliver request to request update volume.", ex); - } - } - @Override public void binderDied() { mHandler.post(() -> onConnectionDied(Connection.this)); diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 358cc29e3d64..b1133223e59a 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -334,20 +334,6 @@ class MediaRouter2ServiceImpl { } } - public void requestUpdateVolume2(IMediaRouter2Client client, MediaRoute2Info route, int delta) { - Objects.requireNonNull(client, "client must not be null"); - Objects.requireNonNull(route, "route must not be null"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - requestUpdateVolumeLocked(client, route, delta); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - public void requestCreateClientSession(IMediaRouter2Manager manager, String packageName, MediaRoute2Info route, int requestId) { final long token = Binder.clearCallingIdentity(); @@ -375,21 +361,6 @@ class MediaRouter2ServiceImpl { } } - public void requestUpdateVolume2Manager(IMediaRouter2Manager manager, - MediaRoute2Info route, int delta) { - Objects.requireNonNull(manager, "manager must not be null"); - Objects.requireNonNull(route, "route must not be null"); - - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - requestUpdateVolumeLocked(manager, route, delta); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - @NonNull public List<RoutingSessionInfo> getActiveSessions(IMediaRouter2Manager manager) { final long token = Binder.clearCallingIdentity(); @@ -628,18 +599,6 @@ class MediaRouter2ServiceImpl { } } - private void requestUpdateVolumeLocked(IMediaRouter2Client client, MediaRoute2Info route, - int delta) { - final IBinder binder = client.asBinder(); - Client2Record clientRecord = mAllClientRecords.get(binder); - - if (clientRecord != null) { - clientRecord.mUserRecord.mHandler.sendMessage( - obtainMessage(UserHandler::requestUpdateVolume, - clientRecord.mUserRecord.mHandler, route, delta)); - } - } - private void registerManagerLocked(IMediaRouter2Manager manager, int uid, int pid, String packageName, int userId, boolean trusted) { final IBinder binder = manager.asBinder(); @@ -713,18 +672,6 @@ class MediaRouter2ServiceImpl { } } - private void requestUpdateVolumeLocked(IMediaRouter2Manager manager, MediaRoute2Info route, - int delta) { - final IBinder binder = manager.asBinder(); - ManagerRecord managerRecord = mAllManagerRecords.get(binder); - - if (managerRecord != null) { - managerRecord.mUserRecord.mHandler.sendMessage( - obtainMessage(UserHandler::requestUpdateVolume, - managerRecord.mUserRecord.mHandler, route, delta)); - } - } - private List<RoutingSessionInfo> getActiveSessionsLocked(IMediaRouter2Manager manager) { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); @@ -1459,13 +1406,6 @@ class MediaRouter2ServiceImpl { } } - private void requestUpdateVolume(MediaRoute2Info route, int delta) { - final MediaRoute2Provider provider = findProvider(route.getProviderId()); - if (provider != null) { - provider.requestUpdateVolume(route.getOriginalId(), delta); - } - } - private List<IMediaRouter2Client> getClients() { final List<IMediaRouter2Client> clients = new ArrayList<>(); MediaRouter2ServiceImpl service = mServiceRef.get(); diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index e1d38039b955..57f0328f1c00 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -539,12 +539,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override - public void requestUpdateVolume2(IMediaRouter2Client client, MediaRoute2Info route, int delta) { - mService2.requestUpdateVolume2(client, route, delta); - } - - // Binder call - @Override public void requestSetVolume2Manager(IMediaRouter2Manager manager, MediaRoute2Info route, int volume) { mService2.requestSetVolume2Manager(manager, route, volume); @@ -552,13 +546,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override - public void requestUpdateVolume2Manager(IMediaRouter2Manager manager, - MediaRoute2Info route, int delta) { - mService2.requestUpdateVolume2Manager(manager, route, delta); - } - - // Binder call - @Override public List<RoutingSessionInfo> getActiveSessions(IMediaRouter2Manager manager) { return mService2.getActiveSessions(manager); } diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index 798a781a9d6c..888f7ce74ba4 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -153,11 +153,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { public void requestSetVolume(String routeId, int volume) { } - //TODO: implement method - @Override - public void requestUpdateVolume(String routeId, int delta) { - } - private void initializeDefaultRoute() { mDefaultRoute = new MediaRoute2Info.Builder( DEFAULT_ROUTE_ID, diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 40ea6cfb6d4a..b98bb0831b0e 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -234,12 +234,12 @@ public class Installer extends SystemService { } public void moveCompleteApp(String fromUuid, String toUuid, String packageName, - String dataAppName, int appId, String seInfo, int targetSdkVersion) - throws InstallerException { + String dataAppName, int appId, String seInfo, int targetSdkVersion, + String fromCodePath) throws InstallerException { if (!checkBeforeRemote()) return; try { mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo, - targetSdkVersion); + targetSdkVersion, fromCodePath); } catch (Exception e) { throw InstallerException.from(e); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c14b42dd69c8..e4ec3745e01d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -13978,9 +13978,11 @@ public class PackageManagerService extends IPackageManager.Stub final int appId; final String seinfo; final int targetSdkVersion; + final String fromCodePath; public MoveInfo(int moveId, String fromUuid, String toUuid, String packageName, - String dataAppName, int appId, String seinfo, int targetSdkVersion) { + String dataAppName, int appId, String seinfo, int targetSdkVersion, + String fromCodePath) { this.moveId = moveId; this.fromUuid = fromUuid; this.toUuid = toUuid; @@ -13989,6 +13991,7 @@ public class PackageManagerService extends IPackageManager.Stub this.appId = appId; this.seinfo = seinfo; this.targetSdkVersion = targetSdkVersion; + this.fromCodePath = fromCodePath; } } @@ -15104,7 +15107,8 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mInstaller) { try { mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName, - move.dataAppName, move.appId, move.seinfo, move.targetSdkVersion); + move.dataAppName, move.appId, move.seinfo, move.targetSdkVersion, + move.fromCodePath); } catch (InstallerException e) { Slog.w(TAG, "Failed to move app", e); return PackageManager.INSTALL_FAILED_INTERNAL_ERROR; @@ -22054,6 +22058,7 @@ public class PackageManagerService extends IPackageManager.Stub final PackageFreezer freezer; final int[] installedUserIds; final boolean isCurrentLocationExternal; + final String fromCodePath; // reader synchronized (mLock) { @@ -22110,6 +22115,7 @@ public class PackageManagerService extends IPackageManager.Stub targetSdkVersion = pkg.getTargetSdkVersion(); freezer = freezePackage(packageName, "movePackageInternal"); installedUserIds = ps.queryInstalledUsers(mUserManager.getUserIds(), true); + fromCodePath = pkg.getCodePath(); } final Bundle extras = new Bundle(); @@ -22238,7 +22244,7 @@ public class PackageManagerService extends IPackageManager.Stub final String dataAppName = codeFile.getName(); move = new MoveInfo(moveId, currentVolumeUuid, volumeUuid, packageName, - dataAppName, appId, seinfo, targetSdkVersion); + dataAppName, appId, seinfo, targetSdkVersion, fromCodePath); } else { move = null; } diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java index 6daf5162ebad..6eba59acbc94 100644 --- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java +++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java @@ -402,7 +402,7 @@ class LegacyGlobalActions implements DialogInterface.OnDismissListener, DialogIn public String getStatus() { return mContext.getString( com.android.internal.R.string.bugreport_status, - Build.VERSION.RELEASE, + Build.VERSION.RELEASE_OR_CODENAME, Build.ID); } } diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 96f1219861ec..5c79f6e6391d 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -2480,7 +2480,7 @@ public class StatsPullAtomService extends SystemService { .writeString(Build.BRAND) .writeString(Build.PRODUCT) .writeString(Build.DEVICE) - .writeString(Build.VERSION.RELEASE) + .writeString(Build.VERSION.RELEASE_OR_CODENAME) .writeString(Build.ID) .writeString(Build.VERSION.INCREMENTAL) .writeString(Build.TYPE) diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index 75d87edbc437..f35ba9e69ed7 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -386,6 +386,8 @@ public class ActivityStartController { } else { callingPid = callingUid = -1; } + final int filterCallingUid = ActivityStarter.computeResolveFilterUid( + callingUid, realCallingUid, UserHandle.USER_NULL); final SparseArray<String> startingUidPkgs = new SparseArray<>(); final long origId = Binder.clearCallingIdentity(); try { @@ -408,9 +410,7 @@ public class ActivityStartController { // Collect information about the target of the Intent. ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], - 0 /* startFlags */, null /* profilerInfo */, userId, - ActivityStarter.computeResolveFilterUid( - callingUid, realCallingUid, UserHandle.USER_NULL)); + 0 /* startFlags */, null /* profilerInfo */, userId, filterCallingUid); aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId); if (aInfo != null) { @@ -457,6 +457,7 @@ public class ActivityStartController { Slog.wtf(TAG, sb.toString()); } + final IBinder sourceResultTo = resultTo; final ActivityRecord[] outActivity = new ActivityRecord[1]; // Lock the loop to ensure the activities launched in a sequence. synchronized (mService.mGlobalLock) { @@ -470,7 +471,18 @@ public class ActivityStartController { } return startResult; } - resultTo = outActivity[0] != null ? outActivity[0].appToken : null; + final ActivityRecord started = outActivity[0]; + if (started != null && started.getUid() == filterCallingUid) { + // Only the started activity which has the same uid as the source caller can + // be the caller of next activity. + resultTo = started.appToken; + } else { + resultTo = sourceResultTo; + // Different apps not adjacent to the caller are forced to be new task. + if (i < starters.length - 1) { + starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + } } } } finally { diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 9e3292b59402..c7270f257923 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2493,7 +2493,6 @@ class ActivityStarter { return this; } - @VisibleForTesting Intent getIntent() { return mRequest.intent; } diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml index 0e24b0314b2d..44eb8285c7db 100644 --- a/services/tests/mockingservicestests/AndroidManifest.xml +++ b/services/tests/mockingservicestests/AndroidManifest.xml @@ -17,6 +17,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.frameworks.mockingservicestests"> + <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> <uses-permission android:name="android.permission.HARDWARE_TEST"/> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index d2ddff3627b9..1212f2082404 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -65,6 +65,8 @@ <uses-permission android:name="android.permission.WATCH_APPOPS" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.SUSPEND_APPS"/> + <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" /> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/> <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/> <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml index 180deb5c4dcc..dab0a5f0e279 100644 --- a/services/tests/uiservicestests/AndroidManifest.xml +++ b/services/tests/uiservicestests/AndroidManifest.xml @@ -28,6 +28,8 @@ <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> <uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" /> + <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/> + <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" /> <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/> diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp index 5e9ef8efc402..74dfde848191 100644 --- a/tests/PlatformCompatGating/Android.bp +++ b/tests/PlatformCompatGating/Android.bp @@ -18,14 +18,11 @@ android_test { name: "PlatformCompatGating", // Only compile source java files in this apk. srcs: ["src/**/*.java"], - certificate: "platform", - libs: [ - "android.test.runner", - "android.test.base", - ], static_libs: [ "junit", - "android-support-test", + "androidx.test.runner", + "androidx.test.core", + "androidx.test.ext.junit", "mockito-target-minus-junit4", "truth-prebuilt", "platform-compat-test-rules" diff --git a/tests/PlatformCompatGating/AndroidManifest.xml b/tests/PlatformCompatGating/AndroidManifest.xml index 7f14b83fbc75..c24dc31b7bf3 100644 --- a/tests/PlatformCompatGating/AndroidManifest.xml +++ b/tests/PlatformCompatGating/AndroidManifest.xml @@ -6,6 +6,6 @@ <uses-library android:name="android.test.runner" /> </application> - <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.tests.gating"/> </manifest> diff --git a/tests/PlatformCompatGating/AndroidTest.xml b/tests/PlatformCompatGating/AndroidTest.xml index c62684837332..0c7485b27fb8 100644 --- a/tests/PlatformCompatGating/AndroidTest.xml +++ b/tests/PlatformCompatGating/AndroidTest.xml @@ -24,7 +24,6 @@ <test class="com.android.tradefed.testtype.AndroidJUnitTest"> <option name="package" value="com.android.tests.gating"/> - <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/> <option name="hidden-api-checks" value="false"/> </test> </configuration> diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java index dc317f1941c7..c1ce0e99640c 100644 --- a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java +++ b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java @@ -18,8 +18,9 @@ package com.android.tests.gating; import static com.google.common.truth.Truth.assertThat; import android.compat.testing.PlatformCompatChangeRule; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; import com.android.compat.testing.DummyApi; @@ -81,14 +82,14 @@ public class PlatformCompatGatingTest { @Test @EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) public void testDummyGatingPositiveSystemServer() { - assertThat( - DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isTrue(); + assertThat(DummyApi.dummySystemServer( + InstrumentationRegistry.getInstrumentation().getTargetContext())).isTrue(); } @Test @DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER}) public void testDummyGatingNegativeSystemServer() { - assertThat( - DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isFalse(); + assertThat(DummyApi.dummySystemServer( + InstrumentationRegistry.getInstrumentation().getTargetContext())).isFalse(); } } diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatPermissionsTest.java b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatPermissionsTest.java new file mode 100644 index 000000000000..9b9e5815a588 --- /dev/null +++ b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatPermissionsTest.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.tests.gating; + +import static android.Manifest.permission.LOG_COMPAT_CHANGE; +import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG; +import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; + +import android.app.Instrumentation; +import android.app.UiAutomation; +import android.compat.Compatibility.ChangeConfig; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Process; +import android.os.ServiceManager; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.internal.compat.CompatibilityChangeConfig; +import com.android.internal.compat.IPlatformCompat; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.HashSet; +import java.util.Set; + +@RunWith(JUnit4.class) +public final class PlatformCompatPermissionsTest { + + // private Context mContext; + private IPlatformCompat mPlatformCompat; + + @Rule + public final ExpectedException thrown = ExpectedException.none(); + private Context mContext; + private UiAutomation mUiAutomation; + private PackageManager mPackageManager; + + @Before + public void setUp() { + // mContext; + mPlatformCompat = IPlatformCompat.Stub + .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + mUiAutomation = instrumentation.getUiAutomation(); + mContext = instrumentation.getTargetContext(); + + mPackageManager = mContext.getPackageManager(); + } + + @After + public void tearDown() { + + mUiAutomation.dropShellPermissionIdentity(); + } + + @Test + public void reportChange_noLogCompatChangePermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.reportChange(1, mPackageManager.getApplicationInfo(packageName, 0)); + } + + @Test + public void reportChange_logCompatChangePermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.reportChange(1, mPackageManager.getApplicationInfo(packageName, 0)); + } + + @Test + public void reportChangeByPackageName_noLogCompatChangePermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.reportChangeByPackageName(1, packageName, 0); + } + + @Test + public void reportChangeByPackageName_logCompatChangePermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.reportChangeByPackageName(1, packageName, 0); + } + + @Test + public void reportChangeByUid_noLogCompatChangePermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + + mPlatformCompat.reportChangeByUid(1, Process.myUid()); + } + + @Test + public void reportChangeByUid_logCompatChangePermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE); + + mPlatformCompat.reportChangeByUid(1, Process.myUid()); + } + + @Test + public void isChangeEnabled_noReadCompatConfigPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0)); + } + + @Test + public void isChangeEnabled_noLogCompatChangeConfigPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0)); + } + + @Test + public void isChangeEnabled_readAndLogCompatChangeConfigPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0)); + } + + @Test + public void isChangeEnabledByPackageName_noReadCompatConfigPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0); + } + + @Test + public void isChangeEnabledByPackageName_noLogompatConfigPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0); + } + + @Test + public void isChangeEnabledByPackageName_readAndLogCompatChangeConfigPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE); + final String packageName = mContext.getPackageName(); + + mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0); + } + + @Test + public void isChangeEnabledByUid_noReadCompatConfigPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + + mPlatformCompat.isChangeEnabledByUid(1, Process.myUid()); + } + + @Test + public void isChangeEnabledByUid_noLogCompatChangePermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG); + + mPlatformCompat.isChangeEnabledByUid(1, Process.myUid()); + } + + @Test + public void isChangeEnabledByUid_readAndLogCompatChangeConfigPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE); + + mPlatformCompat.isChangeEnabledByUid(1, Process.myUid()); + } + + @Test + public void setOverrides_noOverridesPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + ChangeConfig changeConfig = new ChangeConfig(enabled, disabled); + CompatibilityChangeConfig compatibilityChangeConfig = + new CompatibilityChangeConfig(changeConfig); + + mPlatformCompat.setOverrides(compatibilityChangeConfig, "foo.bar"); + } + @Test + public void setOverrides_overridesPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG); + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + ChangeConfig changeConfig = new ChangeConfig(enabled, disabled); + CompatibilityChangeConfig compatibilityChangeConfig = + new CompatibilityChangeConfig(changeConfig); + + mPlatformCompat.setOverrides(compatibilityChangeConfig, "foo.bar"); + } + + @Test + public void setOverridesForTest_noOverridesPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + ChangeConfig changeConfig = new ChangeConfig(enabled, disabled); + CompatibilityChangeConfig compatibilityChangeConfig = + new CompatibilityChangeConfig(changeConfig); + + mPlatformCompat.setOverridesForTest(compatibilityChangeConfig, "foo.bar"); + } + @Test + public void setOverridesForTest_overridesPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG); + Set<Long> enabled = new HashSet<>(); + Set<Long> disabled = new HashSet<>(); + ChangeConfig changeConfig = new ChangeConfig(enabled, disabled); + CompatibilityChangeConfig compatibilityChangeConfig = + new CompatibilityChangeConfig(changeConfig); + + mPlatformCompat.setOverridesForTest(compatibilityChangeConfig, "foo.bar"); + } + + @Test + public void clearOverrides_noOverridesPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + + mPlatformCompat.clearOverrides("foo.bar"); + } + @Test + public void clearOverrides_overridesPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG); + + mPlatformCompat.clearOverrides("foo.bar"); + } + + @Test + public void clearOverridesForTest_noOverridesPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + + mPlatformCompat.clearOverridesForTest("foo.bar"); + } + @Test + public void clearOverridesForTest_overridesPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG); + + mPlatformCompat.clearOverridesForTest("foo.bar"); + } + + @Test + public void clearOverride_noOverridesPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + + mPlatformCompat.clearOverride(1, "foo.bar"); + } + @Test + public void clearOverride_overridesPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG); + + mPlatformCompat.clearOverride(1, "foo.bar"); + } + + @Test + public void listAllChanges_noReadCompatConfigPermission_throwsSecurityException() + throws Throwable { + thrown.expect(SecurityException.class); + + mPlatformCompat.listAllChanges(); + } + @Test + public void listAllChanges_readCompatConfigPermission_noThrow() + throws Throwable { + mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG); + + mPlatformCompat.listAllChanges(); + } +} diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp index 8211ef523ee7..10fa2dc0d7c6 100644 --- a/tests/PlatformCompatGating/test-rules/Android.bp +++ b/tests/PlatformCompatGating/test-rules/Android.bp @@ -19,7 +19,7 @@ java_library { srcs: ["src/**/*.java"], static_libs: [ "junit", - "android-support-test", + "androidx.test.core", "truth-prebuilt", "core-compat-test-rules" ], diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java index 932ec643d478..d6846faa5c00 100644 --- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java +++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java @@ -16,13 +16,17 @@ package android.compat.testing; +import android.Manifest; import android.app.Instrumentation; +import android.app.UiAutomation; import android.compat.Compatibility; import android.compat.Compatibility.ChangeConfig; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; -import android.support.test.InstrumentationRegistry; + +import androidx.test.platform.app.InstrumentationRegistry; + import com.android.internal.compat.CompatibilityChangeConfig; import com.android.internal.compat.IPlatformCompat; @@ -83,12 +87,17 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { @Override public void evaluate() throws Throwable { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + UiAutomation uiAutomation = instrumentation.getUiAutomation(); String packageName = instrumentation.getTargetContext().getPackageName(); IPlatformCompat platformCompat = IPlatformCompat.Stub .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); if (platformCompat == null) { throw new IllegalStateException("Could not get IPlatformCompat service!"); } + uiAutomation.adoptShellPermissionIdentity( + Manifest.permission.LOG_COMPAT_CHANGE, + Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG, + Manifest.permission.READ_COMPAT_CHANGE_CONFIG); Compatibility.setOverrides(mConfig); try { platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig), @@ -101,6 +110,7 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { } catch (RemoteException e) { throw new RuntimeException("Could not call IPlatformCompat binder method!", e); } finally { + uiAutomation.dropShellPermissionIdentity(); Compatibility.clearOverrides(); } } diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp index d3958a65c704..a251c053e004 100644 --- a/tools/stats_log_api_gen/Android.bp +++ b/tools/stats_log_api_gen/Android.bp @@ -30,7 +30,7 @@ cc_binary_host { "utils.cpp", ], cflags: [ - "-DSTATS_SCHEMA_LEGACY", + //"-DSTATS_SCHEMA_LEGACY", "-Wall", "-Werror", ], diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp index a68c3a208869..12c050d8ef8d 100644 --- a/tools/stats_log_api_gen/java_writer_q.cpp +++ b/tools/stats_log_api_gen/java_writer_q.cpp @@ -175,9 +175,7 @@ int write_java_methods_q_schema( indent.c_str()); fprintf(out, "%s android.util.SparseArray<Float> floatMap = null;\n", indent.c_str()); - fprintf(out, - "%s int keyValuePairSize = LIST_TYPE_OVERHEAD * 5;\n", - indent.c_str()); + fprintf(out, "%s int keyValuePairSize = LIST_TYPE_OVERHEAD;\n", indent.c_str()); fprintf(out, "%s for (int i = 0; i < count; i++) {\n", indent.c_str()); fprintf(out, @@ -360,8 +358,9 @@ int write_java_methods_q_schema( requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT; requiredHelpers |= JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS; fprintf(out, - "%s writeKeyValuePairs(buff, pos, intMap, longMap, stringMap, " - "floatMap);\n", indent.c_str()); + "%s writeKeyValuePairs(buff, pos, (byte) count, intMap, longMap, " + "stringMap, floatMap);\n", + indent.c_str()); fprintf(out, "%s pos += keyValuePairSize;\n", indent.c_str()); break; default: @@ -472,7 +471,8 @@ void write_java_helpers_for_q_schema_methods( } if (requiredHelpers & JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS) { - fprintf(out, "%sprivate static void writeKeyValuePairs(byte[] buff, int pos,\n", + fprintf(out, + "%sprivate static void writeKeyValuePairs(byte[] buff, int pos, byte numPairs,\n", indent.c_str()); fprintf(out, "%s final android.util.SparseIntArray intMap,\n", indent.c_str()); fprintf(out, "%s final android.util.SparseLongArray longMap,\n", indent.c_str()); @@ -483,15 +483,12 @@ void write_java_helpers_for_q_schema_methods( // Start list of lists. fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) 4;\n", indent.c_str()); + fprintf(out, "%s buff[pos + 1] = (byte) numPairs;\n", indent.c_str()); fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); // Write integers. fprintf(out, "%s final int intMapSize = null == intMap ? 0 : intMap.size();\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) intMapSize;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); fprintf(out, "%s for (int i = 0; i < intMapSize; i++) {\n", indent.c_str()); fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); @@ -509,9 +506,6 @@ void write_java_helpers_for_q_schema_methods( // Write longs. fprintf(out, "%s final int longMapSize = null == longMap ? 0 : longMap.size();\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) longMapSize;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); fprintf(out, "%s for (int i = 0; i < longMapSize; i++) {\n", indent.c_str()); fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); @@ -529,9 +523,6 @@ void write_java_helpers_for_q_schema_methods( // Write Strings. fprintf(out, "%s final int stringMapSize = null == stringMap ? 0 : stringMap.size();\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) stringMapSize;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); fprintf(out, "%s for (int i = 0; i < stringMapSize; i++) {\n", indent.c_str()); fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); @@ -556,9 +547,6 @@ void write_java_helpers_for_q_schema_methods( // Write floats. fprintf(out, "%s final int floatMapSize = null == floatMap ? 0 : floatMap.size();\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) floatMapSize;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); fprintf(out, "%s for (int i = 0; i < floatMapSize; i++) {\n", indent.c_str()); fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); diff --git a/tools/streaming_proto/cpp/main.cpp b/tools/streaming_proto/cpp/main.cpp index d6b9d81137ac..fe9a438d81d7 100644 --- a/tools/streaming_proto/cpp/main.cpp +++ b/tools/streaming_proto/cpp/main.cpp @@ -33,13 +33,13 @@ write_enum(stringstream& text, const EnumDescriptorProto& enu, const string& ind if (GENERATE_MAPPING) { string name = make_constant_name(enu.name()); string prefix = name + "_"; - text << indent << "const int _ENUM_" << name << "_COUNT = " << N << ";" << endl; - text << indent << "const char* _ENUM_" << name << "_NAMES[" << N << "] = {" << endl; + text << indent << "static const int _ENUM_" << name << "_COUNT = " << N << ";" << endl; + text << indent << "static const char* _ENUM_" << name << "_NAMES[" << N << "] = {" << endl; for (int i=0; i<N; i++) { text << indent << INDENT << "\"" << stripPrefix(enu.value(i).name(), prefix) << "\"," << endl; } text << indent << "};" << endl; - text << indent << "const int _ENUM_" << name << "_VALUES[" << N << "] = {" << endl; + text << indent << "static const int _ENUM_" << name << "_VALUES[" << N << "] = {" << endl; for (int i=0; i<N; i++) { text << indent << INDENT << make_constant_name(enu.value(i).name()) << "," << endl; } @@ -102,13 +102,13 @@ write_message(stringstream& text, const DescriptorProto& message, const string& if (GENERATE_MAPPING) { N = message.field_size(); - text << indented << "const int _FIELD_COUNT = " << N << ";" << endl; - text << indented << "const char* _FIELD_NAMES[" << N << "] = {" << endl; + text << indented << "static const int _FIELD_COUNT = " << N << ";" << endl; + text << indented << "static const char* _FIELD_NAMES[" << N << "] = {" << endl; for (int i=0; i<N; i++) { text << indented << INDENT << "\"" << message.field(i).name() << "\"," << endl; } text << indented << "};" << endl; - text << indented << "const uint64_t _FIELD_IDS[" << N << "] = {" << endl; + text << indented << "static const uint64_t _FIELD_IDS[" << N << "] = {" << endl; for (int i=0; i<N; i++) { text << indented << INDENT << make_constant_name(message.field(i).name()) << "," << endl; } @@ -152,7 +152,7 @@ write_header_file(CodeGeneratorResponse* response, const FileDescriptorProto& fi write_message(text, file_descriptor.message_type(i), ""); } - for (vector<string>::iterator it = namespaces.begin(); it != namespaces.end(); it++) { + for (vector<string>::reverse_iterator it = namespaces.rbegin(); it != namespaces.rend(); it++) { text << "} // " << *it << endl; } |