diff options
73 files changed, 1752 insertions, 1001 deletions
diff --git a/api/current.txt b/api/current.txt index d11b6a4c6525..747a3f5d7c53 100644 --- a/api/current.txt +++ b/api/current.txt @@ -35052,7 +35052,7 @@ package android.os { method public android.os.PowerManager.WakeLock newWakeLock(int, String); method public void reboot(String); method public void registerThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback, @NonNull java.util.concurrent.Executor); - method public void unregisterThermalStatusCallback(android.os.PowerManager.ThermalStatusCallback); + method public void unregisterThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback); field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000 field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED"; field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED"; diff --git a/api/system-current.txt b/api/system-current.txt index b974995e8d68..c60b94e48d0b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -285,9 +285,11 @@ package android.app { method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void forceStopPackage(String); method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public static int getCurrentUser(); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getPackageImportance(String); + method @NonNull public java.util.Collection<java.util.Locale> getSupportedLocales(); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int); method @RequiresPermission(android.Manifest.permission.KILL_UID) public void killUid(int, String); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener); + method public void setDeviceLocales(@NonNull android.os.LocaleList); method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public static void setPersistentVrThread(int); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle); } @@ -1366,6 +1368,7 @@ package android.content { field public static final String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE"; field public static final String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS"; field public static final String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION"; + field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION"; field public static final String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS"; field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_DEFAULT_APP = "android.intent.action.MANAGE_DEFAULT_APP"; field public static final String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS"; @@ -5302,6 +5305,10 @@ package android.os { field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR; } + public final class LocaleList implements android.os.Parcelable { + method public static boolean isPseudoLocale(@Nullable android.icu.util.ULocale); + } + public final class NativeHandle implements java.io.Closeable { ctor public NativeHandle(); ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean); @@ -6301,20 +6308,11 @@ package android.service.autofill.augmented { } public abstract class PresentationParams { - method public int getFlags(); - method @Nullable public android.service.autofill.augmented.PresentationParams.Area getFullArea(); method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea(); - field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2 - field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4 - field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8 - field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1 - field public static final int FLAG_HOST_IME = 16; // 0x10 - field public static final int FLAG_HOST_SYSTEM = 32; // 0x20 } public abstract static class PresentationParams.Area { method @NonNull public android.graphics.Rect getBounds(); - method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSubArea(@NonNull android.graphics.Rect); } } diff --git a/api/test-current.txt b/api/test-current.txt index adc7279b4ef8..47d38a7d2f3a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -996,6 +996,7 @@ package android.net { method public int[] getCapabilities(); method public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(android.net.NetworkCapabilities); + field public static final int TRANSPORT_TEST = 7; // 0x7 } public class NetworkStack { @@ -2074,20 +2075,11 @@ package android.service.autofill.augmented { } public abstract class PresentationParams { - method public int getFlags(); - method @Nullable public android.service.autofill.augmented.PresentationParams.Area getFullArea(); method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea(); - field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2 - field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4 - field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8 - field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1 - field public static final int FLAG_HOST_IME = 16; // 0x10 - field public static final int FLAG_HOST_SYSTEM = 32; // 0x20 } public abstract static class PresentationParams.Area { method @NonNull public android.graphics.Rect getBounds(); - method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSubArea(@NonNull android.graphics.Rect); } } diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp index 5f3aae3ab93a..4579ca6008ef 100644 --- a/cmds/statsd/tests/StatsLogProcessor_test.cpp +++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp @@ -297,7 +297,8 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { // Setup a simple config, no activation StatsdConfig config1; - config1.set_id(12341); + int64_t cfgId1 = 12341; + config1.set_id(cfgId1); config1.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher(); *config1.add_atom_matcher() = wakelockAcquireMatcher; @@ -314,14 +315,12 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { countMetric2->set_what(wakelockAcquireMatcher.id()); countMetric2->set_bucket(FIVE_MINUTES); - ConfigKey cfgKey1(uid, 12341); - long timeBase1 = 1; - sp<StatsLogProcessor> processor = - CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1); + ConfigKey cfgKey1(uid, cfgId1); // Add another config, with two metrics, one with activation StatsdConfig config2; - config2.set_id(12342); + int64_t cfgId2 = 12342; + config2.set_id(cfgId2); config2.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. *config2.add_atom_matcher() = wakelockAcquireMatcher; @@ -344,11 +343,12 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { metric3ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id()); metric3ActivationTrigger->set_ttl_seconds(100); - ConfigKey cfgKey2(uid, 12342); + ConfigKey cfgKey2(uid, cfgId2); // Add another config, with two metrics, both with activations StatsdConfig config3; - config3.set_id(12342); + int64_t cfgId3 = 12343; + config3.set_id(cfgId3); config3.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. *config3.add_atom_matcher() = wakelockAcquireMatcher; @@ -376,14 +376,37 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { metric6ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id()); metric6ActivationTrigger->set_ttl_seconds(200); - ConfigKey cfgKey3(uid, 12343); + ConfigKey cfgKey3(uid, cfgId3); - processor->OnConfigUpdated(2, cfgKey2, config2); - processor->OnConfigUpdated(3, cfgKey3, config3); + sp<UidMap> m = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> subscriberAlarmMonitor; + vector<int64_t> activeConfigsBroadcast; - EXPECT_EQ(3, processor->mMetricsManagers.size()); - auto it = processor->mMetricsManagers.find(cfgKey1); - EXPECT_TRUE(it != processor->mMetricsManagers.end()); + long timeBase1 = 1; + int broadcastCount = 0; + StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, + timeBase1, [](const ConfigKey& key) { return true; }, + [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid, + const vector<int64_t>& activeConfigs) { + broadcastCount++; + EXPECT_EQ(broadcastUid, uid); + activeConfigsBroadcast.clear(); + activeConfigsBroadcast.insert(activeConfigsBroadcast.end(), + activeConfigs.begin(), activeConfigs.end()); + return true; + }); + + processor.OnConfigUpdated(1, cfgKey1, config1); + processor.OnConfigUpdated(2, cfgKey2, config2); + processor.OnConfigUpdated(3, cfgKey3, config3); + + EXPECT_EQ(3, processor.mMetricsManagers.size()); + + // Expect the first config and both metrics in it to be active. + auto it = processor.mMetricsManagers.find(cfgKey1); + EXPECT_TRUE(it != processor.mMetricsManagers.end()); auto& metricsManager1 = it->second; EXPECT_TRUE(metricsManager1->isActive()); @@ -407,8 +430,9 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { auto& metricProducer2 = *metricIt; EXPECT_TRUE(metricProducer2->isActive()); - it = processor->mMetricsManagers.find(cfgKey2); - EXPECT_TRUE(it != processor->mMetricsManagers.end()); + // Expect config 2 to be active. Metric 3 shouldn't be active, metric 4 should be active. + it = processor.mMetricsManagers.find(cfgKey2); + EXPECT_TRUE(it != processor.mMetricsManagers.end()); auto& metricsManager2 = it->second; EXPECT_TRUE(metricsManager2->isActive()); @@ -432,8 +456,9 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { auto& metricProducer4 = *metricIt; EXPECT_TRUE(metricProducer4->isActive()); - it = processor->mMetricsManagers.find(cfgKey3); - EXPECT_TRUE(it != processor->mMetricsManagers.end()); + // Expect the third config and both metrics in it to be inactive. + it = processor.mMetricsManagers.find(cfgKey3); + EXPECT_TRUE(it != processor.mMetricsManagers.end()); auto& metricsManager3 = it->second; EXPECT_FALSE(metricsManager3->isActive()); @@ -457,10 +482,30 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { auto& metricProducer6 = *metricIt; EXPECT_FALSE(metricProducer6->isActive()); + // No broadcast for active configs should have happened yet. + EXPECT_EQ(broadcastCount, 0); + + // Activate all 3 metrics that were not active. std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")}; auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); + // Assert that all 3 configs are active. + EXPECT_TRUE(metricsManager1->isActive()); + EXPECT_TRUE(metricsManager2->isActive()); + EXPECT_TRUE(metricsManager3->isActive()); + + // A broadcast should have happened, and all 3 configs should be active in the broadcast. + EXPECT_EQ(broadcastCount, 1); + EXPECT_EQ(activeConfigsBroadcast.size(), 3); + EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId1) + != activeConfigsBroadcast.end()); + EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId2) + != activeConfigsBroadcast.end()); + EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId3) + != activeConfigsBroadcast.end()); + + // When we shut down, metrics 3 & 5 have 100ns remaining, metric 6 has 100s + 100ns. int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC; EXPECT_TRUE(metricProducer3->isActive()); int64_t ttl3 = metricProducer3->getRemainingTtlNs(shutDownTime); @@ -472,8 +517,9 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { int64_t ttl6 = metricProducer6->getRemainingTtlNs(shutDownTime); EXPECT_EQ(100 + 100 * NS_PER_SEC, ttl6); - processor->WriteMetricsActivationToDisk(timeBase1 + 100 * NS_PER_SEC); + processor.WriteMetricsActivationToDisk(shutDownTime); + // Create a second StatsLogProcessor and push the same 3 configs. long timeBase2 = 1000; sp<StatsLogProcessor> processor2 = CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1); @@ -481,6 +527,8 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { processor2->OnConfigUpdated(timeBase2, cfgKey3, config3); EXPECT_EQ(3, processor2->mMetricsManagers.size()); + + // First config and both metrics are active. it = processor2->mMetricsManagers.find(cfgKey1); EXPECT_TRUE(it != processor2->mMetricsManagers.end()); auto& metricsManager1001 = it->second; @@ -506,6 +554,7 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { auto& metricProducer1002 = *metricIt; EXPECT_TRUE(metricProducer1002->isActive()); + // Second config is active. Metric 3 is inactive, metric 4 is active. it = processor2->mMetricsManagers.find(cfgKey2); EXPECT_TRUE(it != processor2->mMetricsManagers.end()); auto& metricsManager1002 = it->second; @@ -531,6 +580,7 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { auto& metricProducer1004 = *metricIt; EXPECT_TRUE(metricProducer1004->isActive()); + // Config 3 is inactive. both metrics are inactive. it = processor2->mMetricsManagers.find(cfgKey3); EXPECT_TRUE(it != processor2->mMetricsManagers.end()); auto& metricsManager1003 = it->second; @@ -557,6 +607,7 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { auto& metricProducer1006 = *metricIt; EXPECT_FALSE(metricProducer1006->isActive()); + // Assert that all 3 metrics with activation are inactive and that the ttls were properly set. EXPECT_FALSE(metricProducer1003->isActive()); const auto& activation1003 = metricProducer1003->mEventActivationMap.begin()->second; EXPECT_EQ(100 * NS_PER_SEC, activation1003.ttl_ns); @@ -572,12 +623,16 @@ TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) { processor2->LoadMetricsActivationFromDisk(); + // After loading activations from disk, assert that all 3 metrics are active. EXPECT_TRUE(metricProducer1003->isActive()); EXPECT_EQ(timeBase2 + ttl3 - activation1003.ttl_ns, activation1003.activation_ns); EXPECT_TRUE(metricProducer1005->isActive()); EXPECT_EQ(timeBase2 + ttl5 - activation1005.ttl_ns, activation1005.activation_ns); EXPECT_TRUE(metricProducer1006->isActive()); EXPECT_EQ(timeBase2 + ttl6 - activation1006.ttl_ns, activation1003.activation_ns); + + // Make sure no more broadcasts have happened. + EXPECT_EQ(broadcastCount, 1); } TEST(StatsLogProcessorTest, TestActivationOnBoot) { diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp index 29e86f3f9456..85d8a5613a8b 100644 --- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp +++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp @@ -66,17 +66,42 @@ TEST(MetricActivationE2eTest, TestCountMetric) { auto config = CreateStatsdConfig(); int64_t bucketStartTimeNs = 10000000000; - int64_t bucketSizeNs = - TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; - - ConfigKey cfgKey; - auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); - EXPECT_EQ(processor->mMetricsManagers.size(), 1u); - EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); - sp<MetricProducer> metricProducer = - processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]; + int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; + + int uid = 12345; + int64_t cfgId = 98765; + ConfigKey cfgKey(uid, cfgId); + + sp<UidMap> m = new UidMap(); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + sp<AlarmMonitor> anomalyAlarmMonitor; + sp<AlarmMonitor> subscriberAlarmMonitor; + vector<int64_t> activeConfigsBroadcast; + + long timeBase1 = 1; + int broadcastCount = 0; + StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, + bucketStartTimeNs, [](const ConfigKey& key) { return true; }, + [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid, + const vector<int64_t>& activeConfigs) { + broadcastCount++; + EXPECT_EQ(broadcastUid, uid); + activeConfigsBroadcast.clear(); + activeConfigsBroadcast.insert(activeConfigsBroadcast.end(), + activeConfigs.begin(), activeConfigs.end()); + return true; + }); + + processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config); + + EXPECT_EQ(processor.mMetricsManagers.size(), 1u); + sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second; + EXPECT_TRUE(metricsManager->isConfigValid()); + EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1); + sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0]; auto& eventActivationMap = metricProducer->mEventActivationMap; + EXPECT_FALSE(metricsManager->isActive()); EXPECT_FALSE(metricProducer->mIsActive); // Two activations: one is triggered by battery saver mode (tracker index 0), the other is // triggered by screen on event (tracker index 2). @@ -93,13 +118,19 @@ TEST(MetricActivationE2eTest, TestCountMetric) { std::unique_ptr<LogEvent> event; event = CreateAppCrashEvent(111, bucketStartTimeNs + 5); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); + EXPECT_FALSE(metricsManager->isActive()); EXPECT_FALSE(metricProducer->mIsActive); + EXPECT_EQ(broadcastCount, 0); // Activated by battery save mode. event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); + EXPECT_TRUE(metricsManager->isActive()); EXPECT_TRUE(metricProducer->mIsActive); + EXPECT_EQ(broadcastCount, 1); + EXPECT_EQ(activeConfigsBroadcast.size(), 1); + EXPECT_EQ(activeConfigsBroadcast[0], cfgId); EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive); EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10); EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC); @@ -109,12 +140,13 @@ TEST(MetricActivationE2eTest, TestCountMetric) { // First processed event. event = CreateAppCrashEvent(222, bucketStartTimeNs + 15); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); // Activated by screen on event. event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 20); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); + EXPECT_TRUE(metricsManager->isActive()); EXPECT_TRUE(metricProducer->mIsActive); EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive); EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10); @@ -126,7 +158,8 @@ TEST(MetricActivationE2eTest, TestCountMetric) { // 2nd processed event. // The activation by screen_on event expires, but the one by battery save mode is still active. event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); + EXPECT_TRUE(metricsManager->isActive()); EXPECT_TRUE(metricProducer->mIsActive); EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive); EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10); @@ -134,15 +167,21 @@ TEST(MetricActivationE2eTest, TestCountMetric) { EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive); EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + 20); EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC); + // No new broadcast since the config should still be active. + EXPECT_EQ(broadcastCount, 1); // 3rd processed event. event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); // All activations expired. event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); + EXPECT_FALSE(metricsManager->isActive()); EXPECT_FALSE(metricProducer->mIsActive); + // New broadcast since the config is no longer active. + EXPECT_EQ(broadcastCount, 2); + EXPECT_EQ(activeConfigsBroadcast.size(), 0); EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive); EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10); EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC); @@ -153,8 +192,12 @@ TEST(MetricActivationE2eTest, TestCountMetric) { // Re-activate. event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); + EXPECT_TRUE(metricsManager->isActive()); EXPECT_TRUE(metricProducer->mIsActive); + EXPECT_EQ(broadcastCount, 3); + EXPECT_EQ(activeConfigsBroadcast.size(), 1); + EXPECT_EQ(activeConfigsBroadcast[0], cfgId); EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive); EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10); EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC); @@ -163,11 +206,11 @@ TEST(MetricActivationE2eTest, TestCountMetric) { EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC); event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1); - processor->OnLogEvent(event.get()); + processor.OnLogEvent(event.get()); ConfigMetricsReportList reports; vector<uint8_t> buffer; - processor->onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true, + processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true, ADB_DUMP, &buffer); EXPECT_TRUE(buffer.size() > 0); EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index ca3c72627e3b..5d4f988c3630 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -55,6 +55,7 @@ import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.IBinder; +import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; @@ -68,6 +69,7 @@ import android.util.DisplayMetrics; import android.util.Singleton; import android.util.Size; +import com.android.internal.app.LocalePicker; import com.android.internal.app.procstats.ProcessStats; import com.android.internal.os.RoSystemProperties; import com.android.internal.os.TransferPipe; @@ -84,7 +86,9 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Locale; /** * <p> @@ -3451,6 +3455,35 @@ public class ActivityManager { } /** + * Sets the current locales of the device. Calling app must have the permission + * {@code android.permission.CHANGE_CONFIGURATION} and + * {@code android.permission.WRITE_SETTINGS}. + * + * @hide + */ + @SystemApi + public void setDeviceLocales(@NonNull LocaleList locales) { + LocalePicker.updateLocales(locales); + } + + /** + * Returns a list of supported locales by this system. It includes all locales that are + * selectable by the user, potentially including locales that the framework does not have + * translated resources for. To get locales that the framework has translated resources for, use + * {@code Resources.getSystem().getAssets().getLocales()} instead. + * + * @hide + */ + @SystemApi + public @NonNull Collection<Locale> getSupportedLocales() { + ArrayList<Locale> locales = new ArrayList<>(); + for (String localeTag : LocalePicker.getSupportedLocales(mContext)) { + locales.add(Locale.forLanguageTag(localeTag)); + } + return locales; + } + + /** * Get the device configuration attributes. */ public ConfigurationInfo getDeviceConfigurationInfo() { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index d781a96420c7..a965dde5a1a4 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1790,6 +1790,35 @@ public class Intent implements Parcelable, Cloneable { "android.intent.action.MANAGE_APP_PERMISSIONS"; /** + * Activity action: Launch UI to manage a specific permissions of an app. + * <p> + * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permission + * will be managed by the launched UI. + * </p> + * <p> + * Input: {@link #EXTRA_PERMISSION_NAME} specifies the (individual) permission + * that should be managed by the launched UI. + * </p> + * <p> + * <li> {@link #EXTRA_USER} specifies the UserHandle of the user that owns the app. + * </p> + * <p> + * Output: Nothing. + * </p> + * + * @see #EXTRA_PACKAGE_NAME + * @see #EXTRA_PERMISSION_NAME + * @see #EXTRA_USER + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_APP_PERMISSION = + "android.intent.action.MANAGE_APP_PERMISSION"; + + /** * Activity action: Launch UI to manage permissions. * <p> * Input: Nothing. diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index cfe35b061151..270e3879a71f 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -163,6 +163,30 @@ public abstract class PackageManagerInternal { } /** + * Provider for default home + */ + public interface DefaultHomeProvider { + + /** + * Get the package name of the default home. + * + * @param userId the user id + * + * @return the package name of the default home, or {@code null} if none + */ + @Nullable + String getDefaultHome(@UserIdInt int userId); + + /** + * Set the package name of the default home. + * + * @param packageName package name of the default home, or {@code null} to remove + * @param userId the user id + */ + void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId); + } + + /** * Sets the location provider packages provider. * @param provider The packages provider. */ @@ -886,4 +910,11 @@ public abstract class PackageManagerInternal { * @param provider the provider */ public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider); + + /** + * Sets the default home provider. + * + * @param provider the provider + */ + public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider); } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 2aca55aacf7a..68d36de19963 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -678,11 +678,20 @@ public class ConnectivityManager { @Deprecated public static final int TYPE_VPN = 17; + /** + * A network that is exclusively meant to be used for testing + * + * @deprecated Use {@link NetworkCapabilities} instead. + * @hide + */ + @Deprecated + public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused. + /** {@hide} */ - public static final int MAX_RADIO_TYPE = TYPE_VPN; + public static final int MAX_RADIO_TYPE = TYPE_TEST; /** {@hide} */ - public static final int MAX_NETWORK_TYPE = TYPE_VPN; + public static final int MAX_NETWORK_TYPE = TYPE_TEST; private static final int MIN_NETWORK_TYPE = TYPE_MOBILE; diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 7e9bda14b199..1d2d81dc4fbe 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -597,6 +597,7 @@ public final class NetworkCapabilities implements Parcelable { TRANSPORT_VPN, TRANSPORT_WIFI_AWARE, TRANSPORT_LOWPAN, + TRANSPORT_TEST, }) public @interface Transport { } @@ -635,10 +636,18 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int TRANSPORT_LOWPAN = 6; + /** + * Indicates this network uses a Test-only virtual interface as a transport. + * + * @hide + */ + @TestApi + public static final int TRANSPORT_TEST = 7; + /** @hide */ public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR; /** @hide */ - public static final int MAX_TRANSPORT = TRANSPORT_LOWPAN; + public static final int MAX_TRANSPORT = TRANSPORT_TEST; /** @hide */ public static boolean isValidTransport(@Transport int transportType) { @@ -652,7 +661,8 @@ public final class NetworkCapabilities implements Parcelable { "ETHERNET", "VPN", "WIFI_AWARE", - "LOWPAN" + "LOWPAN", + "TEST" }; /** diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index ab6dd7c07b42..b7e65b9151b9 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -46,6 +46,7 @@ import com.android.internal.os.BatteryStatsHelper; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -262,6 +263,7 @@ public abstract class BatteryStats implements Parcelable { private static final long BYTES_PER_KB = 1024; private static final long BYTES_PER_MB = 1048576; // 1024^2 private static final long BYTES_PER_GB = 1073741824; //1024^3 + public static final double MILLISECONDS_IN_HOUR = 3600 * 1000; private static final String VERSION_DATA = "vers"; private static final String UID_DATA = "uid"; @@ -482,6 +484,13 @@ public abstract class BatteryStats implements Parcelable { * yield a value of 0 if the device doesn't support power calculations. */ public abstract LongCounter getPowerCounter(); + + /** + * @return a non-null {@link LongCounter} representing total power monitored on the rails + * in mAms (miliamps-milliseconds). The counter may always yield a value of 0 if the device + * doesn't support power rail monitoring. + */ + public abstract LongCounter getMonitoredRailChargeConsumedMaMs(); } /** @@ -1526,6 +1535,9 @@ public abstract class BatteryStats implements Parcelable { // The charge of the battery in micro-Ampere-hours. public int batteryChargeUAh; + public double modemRailChargeMah; + public double wifiRailChargeMah; + // Constants from SCREEN_BRIGHTNESS_* public static final int STATE_BRIGHTNESS_SHIFT = 0; public static final int STATE_BRIGHTNESS_MASK = 0x7; @@ -1738,6 +1750,8 @@ public abstract class BatteryStats implements Parcelable { | ((((int)batteryVoltage)<<16)&0xffff0000); dest.writeInt(bat); dest.writeInt(batteryChargeUAh); + dest.writeDouble(modemRailChargeMah); + dest.writeDouble(wifiRailChargeMah); dest.writeInt(states); dest.writeInt(states2); if (wakelockTag != null) { @@ -1767,6 +1781,8 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = (short)(bat2&0xffff); batteryVoltage = (char)((bat2>>16)&0xffff); batteryChargeUAh = src.readInt(); + modemRailChargeMah = src.readDouble(); + wifiRailChargeMah = src.readDouble(); states = src.readInt(); states2 = src.readInt(); if ((bat&0x10000000) != 0) { @@ -1807,6 +1823,8 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = 0; batteryVoltage = 0; batteryChargeUAh = 0; + modemRailChargeMah = 0; + wifiRailChargeMah = 0; states = 0; states2 = 0; wakelockTag = null; @@ -1835,6 +1853,8 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = o.batteryTemperature; batteryVoltage = o.batteryVoltage; batteryChargeUAh = o.batteryChargeUAh; + modemRailChargeMah = o.modemRailChargeMah; + wifiRailChargeMah = o.wifiRailChargeMah; states = o.states; states2 = o.states2; if (o.wakelockTag != null) { @@ -1867,6 +1887,8 @@ public abstract class BatteryStats implements Parcelable { && batteryTemperature == o.batteryTemperature && batteryVoltage == o.batteryVoltage && batteryChargeUAh == o.batteryChargeUAh + && modemRailChargeMah == o.modemRailChargeMah + && wifiRailChargeMah == o.wifiRailChargeMah && states == o.states && states2 == o.states2 && currentTime == o.currentTime; @@ -3311,7 +3333,8 @@ public abstract class BatteryStats implements Parcelable { if (counter.getIdleTimeCounter().getCountLocked(which) != 0 || counter.getRxTimeCounter().getCountLocked(which) != 0 - || counter.getPowerCounter().getCountLocked(which) != 0) { + || counter.getPowerCounter().getCountLocked(which) != 0 + || counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which) != 0) { return true; } @@ -3345,7 +3368,10 @@ public abstract class BatteryStats implements Parcelable { pw.print(","); pw.print(counter.getRxTimeCounter().getCountLocked(which)); pw.print(","); - pw.print(counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60)); + pw.print(counter.getPowerCounter().getCountLocked(which) / (MILLISECONDS_IN_HOUR)); + pw.print(","); + pw.print(counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which) + / (MILLISECONDS_IN_HOUR)); for (LongCounter c : counter.getTxTimeCounters()) { pw.print(","); pw.print(c.getCountLocked(which)); @@ -3370,7 +3396,10 @@ public abstract class BatteryStats implements Parcelable { proto.write(ControllerActivityProto.RX_DURATION_MS, counter.getRxTimeCounter().getCountLocked(which)); proto.write(ControllerActivityProto.POWER_MAH, - counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60)); + counter.getPowerCounter().getCountLocked(which) / (MILLISECONDS_IN_HOUR)); + proto.write(ControllerActivityProto.MONITORED_RAIL_CHARGE_MAH, + counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which) + / (MILLISECONDS_IN_HOUR)); long tToken; LongCounter[] txCounters = counter.getTxTimeCounters(); @@ -3400,6 +3429,8 @@ public abstract class BatteryStats implements Parcelable { final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); final long powerDrainMaMs = counter.getPowerCounter().getCountLocked(which); + final long monitoredRailChargeConsumedMaMs = + counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which); // Battery real time final long totalControllerActivityTimeMs = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000; @@ -3522,10 +3553,22 @@ public abstract class BatteryStats implements Parcelable { sb.append(" "); sb.append(controllerName); sb.append(" Battery drain: ").append( - BatteryStatsHelper.makemAh(powerDrainMaMs / (double) (1000*60*60))); + BatteryStatsHelper.makemAh(powerDrainMaMs / MILLISECONDS_IN_HOUR)); sb.append("mAh"); pw.println(sb.toString()); } + + if (monitoredRailChargeConsumedMaMs > 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" "); + sb.append(controllerName); + sb.append(" Monitored rail energy drain: ").append( + new DecimalFormat("#.##").format( + monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR)); + sb.append(" mAh"); + pw.println(sb.toString()); + } } /** @@ -6103,6 +6146,8 @@ public abstract class BatteryStats implements Parcelable { int oldTemp = -1; int oldVolt = -1; int oldChargeMAh = -1; + double oldModemRailChargeMah = -1; + double oldWifiRailChargeMah = -1; long lastTime = -1; void reset() { @@ -6114,6 +6159,8 @@ public abstract class BatteryStats implements Parcelable { oldTemp = -1; oldVolt = -1; oldChargeMAh = -1; + oldModemRailChargeMah = -1; + oldWifiRailChargeMah = -1; } public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin, @@ -6299,6 +6346,16 @@ public abstract class BatteryStats implements Parcelable { item.append(checkin ? ",Bcc=" : " charge="); item.append(oldChargeMAh); } + if (oldModemRailChargeMah != rec.modemRailChargeMah) { + oldModemRailChargeMah = rec.modemRailChargeMah; + item.append(checkin ? ",Mrc=" : " modemRailChargemAh="); + item.append(new DecimalFormat("#.##").format(oldModemRailChargeMah)); + } + if (oldWifiRailChargeMah != rec.wifiRailChargeMah) { + oldWifiRailChargeMah = rec.wifiRailChargeMah; + item.append(checkin ? ",Wrc=" : " wifiRailChargemAh="); + item.append(new DecimalFormat("#.##").format(oldWifiRailChargeMah)); + } printBitDescriptions(item, oldState, rec.states, rec.wakelockTag, HISTORY_STATE_DESCRIPTIONS, !checkin); printBitDescriptions(item, oldState2, rec.states2, null, diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java index 87e1b7d21f53..1420e2f5ce10 100644 --- a/core/java/android/os/LocaleList.java +++ b/core/java/android/os/LocaleList.java @@ -20,6 +20,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; +import android.annotation.SystemApi; import android.content.LocaleProto; import android.icu.util.ULocale; import android.util.proto.ProtoOutputStream; @@ -324,6 +325,15 @@ public final class LocaleList implements Parcelable { return LOCALE_EN_XA.equals(locale) || LOCALE_AR_XB.equals(locale); } + /** + * Returns true if locale is a pseudo-locale, false otherwise. + * {@hide} + */ + @SystemApi + public static boolean isPseudoLocale(@Nullable ULocale locale) { + return isPseudoLocale(locale != null ? locale.toLocale() : null); + } + @IntRange(from=0, to=1) private static int matchScore(Locale supported, Locale desired) { if (supported.equals(desired)) { diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 2ecf9d1159f0..cfe2d28f1024 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -1784,7 +1784,7 @@ public final class PowerManager { * * see {@link #registerThermalStatusCallback} */ - public void unregisterThermalStatusCallback(ThermalStatusCallback callback) { + public void unregisterThermalStatusCallback(@NonNull ThermalStatusCallback callback) { Preconditions.checkNotNull(callback, "callback cannnot be null"); synchronized (this) { if (mThermalService == null) { diff --git a/core/java/android/os/connectivity/WifiBatteryStats.java b/core/java/android/os/connectivity/WifiBatteryStats.java index e5341eeeb17b..3639c71ae3b5 100644 --- a/core/java/android/os/connectivity/WifiBatteryStats.java +++ b/core/java/android/os/connectivity/WifiBatteryStats.java @@ -44,6 +44,7 @@ public final class WifiBatteryStats implements Parcelable { private long[] mTimeInStateMs; private long[] mTimeInSupplicantStateMs; private long[] mTimeInRxSignalStrengthLevelMs; + private long mMonitoredRailChargeConsumedMaMs; public static final Parcelable.Creator<WifiBatteryStats> CREATOR = new Parcelable.Creator<WifiBatteryStats>() { @@ -77,6 +78,7 @@ public final class WifiBatteryStats implements Parcelable { out.writeLongArray(mTimeInStateMs); out.writeLongArray(mTimeInRxSignalStrengthLevelMs); out.writeLongArray(mTimeInSupplicantStateMs); + out.writeLong(mMonitoredRailChargeConsumedMaMs); } public void readFromParcel(Parcel in) { @@ -96,6 +98,7 @@ public final class WifiBatteryStats implements Parcelable { in.readLongArray(mTimeInStateMs); in.readLongArray(mTimeInRxSignalStrengthLevelMs); in.readLongArray(mTimeInSupplicantStateMs); + mMonitoredRailChargeConsumedMaMs = in.readLong(); } public long getLoggingDurationMs() { @@ -162,6 +165,10 @@ public final class WifiBatteryStats implements Parcelable { return mTimeInSupplicantStateMs; } + public long getMonitoredRailChargeConsumedMaMs() { + return mMonitoredRailChargeConsumedMaMs; + } + public void setLoggingDurationMs(long t) { mLoggingDurationMs = t; return; @@ -245,6 +252,11 @@ public final class WifiBatteryStats implements Parcelable { return; } + public void setMonitoredRailChargeConsumedMaMs(long monitoredRailEnergyConsumedMaMs) { + mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs; + return; + } + public int describeContents() { return 0; } @@ -274,6 +286,7 @@ public final class WifiBatteryStats implements Parcelable { Arrays.fill(mTimeInRxSignalStrengthLevelMs, 0); mTimeInSupplicantStateMs = new long[BatteryStats.NUM_WIFI_SUPPL_STATES]; Arrays.fill(mTimeInSupplicantStateMs, 0); + mMonitoredRailChargeConsumedMaMs = 0; return; } }
\ No newline at end of file diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java index 81d066d3d656..8695da237f97 100644 --- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java +++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java @@ -61,8 +61,6 @@ import java.util.List; */ @SystemApi @TestApi -// TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service -// in the same package as the test, and that module is compiled with SDK=test_current public abstract class AugmentedAutofillService extends Service { private static final String TAG = AugmentedAutofillService.class.getSimpleName(); diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java index f2a7a35b2825..b989dd9cd4eb 100644 --- a/core/java/android/service/autofill/augmented/FillCallback.java +++ b/core/java/android/service/autofill/augmented/FillCallback.java @@ -31,8 +31,6 @@ import android.util.Log; */ @SystemApi @TestApi -//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service -//in the same package as the test, and that module is compiled with SDK=test_current public final class FillCallback { private static final String TAG = FillCallback.class.getSimpleName(); diff --git a/core/java/android/service/autofill/augmented/FillController.java b/core/java/android/service/autofill/augmented/FillController.java index d7bc893f884a..67f23d599e1d 100644 --- a/core/java/android/service/autofill/augmented/FillController.java +++ b/core/java/android/service/autofill/augmented/FillController.java @@ -38,10 +38,8 @@ import java.util.List; */ @SystemApi @TestApi -//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service -//in the same package as the test, and that module is compiled with SDK=test_current public final class FillController { - private static final String TAG = "FillController"; + private static final String TAG = FillController.class.getSimpleName(); private final AutofillProxy mProxy; diff --git a/core/java/android/service/autofill/augmented/FillRequest.java b/core/java/android/service/autofill/augmented/FillRequest.java index af9905f480df..9a97bb203f5a 100644 --- a/core/java/android/service/autofill/augmented/FillRequest.java +++ b/core/java/android/service/autofill/augmented/FillRequest.java @@ -31,8 +31,6 @@ import android.view.autofill.AutofillValue; @SystemApi // TODO(b/123100811): pass a requestId and/or sessionId? @TestApi -// TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service -// in the same package as the test, and that module is compiled with SDK=test_current public final class FillRequest { final AutofillProxy mProxy; diff --git a/core/java/android/service/autofill/augmented/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java index f1e904a7d8bc..2ac406c5b08c 100644 --- a/core/java/android/service/autofill/augmented/FillResponse.java +++ b/core/java/android/service/autofill/augmented/FillResponse.java @@ -30,8 +30,6 @@ import java.util.List; */ @SystemApi @TestApi -//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service -//in the same package as the test, and that module is compiled with SDK=test_current public final class FillResponse { private final FillWindow mFillWindow; @@ -53,8 +51,6 @@ public final class FillResponse { */ @SystemApi @TestApi - //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service - //in the same package as the test, and that module is compiled with SDK=test_current public static final class Builder { private FillWindow mFillWindow; diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java index 40e3a1219501..6e06754e7b8a 100644 --- a/core/java/android/service/autofill/augmented/FillWindow.java +++ b/core/java/android/service/autofill/augmented/FillWindow.java @@ -63,10 +63,8 @@ import java.io.PrintWriter; */ @SystemApi @TestApi -//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service -//in the same package as the test, and that module is compiled with SDK=test_current public final class FillWindow implements AutoCloseable { - private static final String TAG = "FillWindow"; + private static final String TAG = FillWindow.class.getSimpleName(); private final Object mLock = new Object(); private final CloseGuard mCloseGuard = CloseGuard.get(); diff --git a/core/java/android/service/autofill/augmented/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java index 1fb9032c9af5..334487dd6ab4 100644 --- a/core/java/android/service/autofill/augmented/PresentationParams.java +++ b/core/java/android/service/autofill/augmented/PresentationParams.java @@ -15,32 +15,19 @@ */ package android.service.autofill.augmented; -import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.graphics.Rect; import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy; -import android.util.DebugUtils; import android.view.View; import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; /** * Abstraction of a "Smart Suggestion" component responsible to embed the autofill UI provided by - * the intelligence service. - * - * <p>The Smart Suggestion can embed the autofill UI in 3 distinct places: - * - * <ul> - * <li>A small area associated with suggestions (like a small strip in the top of the IME), - * returned by {@link #getSuggestionArea()} - * <li>The full area (like the full IME window), returned by {@link #getFullArea()} - * <li>A subset of the aforementioned areas, returned by {@link Area#getSubArea(Rect)} - * </ul> + * the augmented autofill service. * * <p>The Smart Suggestion is represented by a {@link Area} object that contains the * dimensions the smart suggestion window, so the service can use it to calculate the size of the @@ -50,54 +37,8 @@ import java.lang.annotation.RetentionPolicy; */ @SystemApi @TestApi -//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service -//in the same package as the test, and that module is compiled with SDK=test_current public abstract class PresentationParams { - /** - * Flag indicating the Smart Suggestion is hosted in the top of its container. - */ - public static final int FLAG_HINT_GRAVITY_TOP = 0x1; - - /** - * Flag indicating the Smart Suggestion is hosted in the bottom of its container. - */ - public static final int FLAG_HINT_GRAVITY_BOTTOM = 0x2; - - /** - * Flag indicating the Smart Suggestion is hosted in the left of its container. - */ - public static final int FLAG_HINT_GRAVITY_LEFT = 0x4; - - /** - * Flag indicating the Smart Suggestion is hosted in the right of its container. - */ - public static final int FLAG_HINT_GRAVITY_RIGHT = 0x8; - - /** - * Flag indicating the Smart Suggestion is hosted by the IME. - */ - public static final int FLAG_HOST_IME = 0x10; - - /** - * Flag indicating the Smart Suggestion is hosted by the Android System as a floating popup - * window. - */ - public static final int FLAG_HOST_SYSTEM = 0x20; - - /** @hide */ - @IntDef(flag = true, prefix = { "FLAG_" }, value = { - FLAG_HINT_GRAVITY_TOP, - FLAG_HINT_GRAVITY_BOTTOM, - FLAG_HINT_GRAVITY_LEFT, - FLAG_HINT_GRAVITY_RIGHT, - FLAG_HOST_IME, - FLAG_HOST_SYSTEM - }) - @Retention(RetentionPolicy.SOURCE) - @interface Flags {} - - // /** @hide */ PresentationParams() {} @@ -112,40 +53,7 @@ public abstract class PresentationParams { return null; } - /** - * Gets the full area for the of the Smart Suggestion provider. - * - * @return full dimensions, or {@code null} if the Smart Suggestion provider does not support - * embeding the UI on its full area. - */ - @Nullable - public Area getFullArea() { - return null; - } - - /** - * Gets flags associated with the Smart Suggestion. - * - * @return any combination of {@link #FLAG_HINT_GRAVITY_TOP}, - * {@link #FLAG_HINT_GRAVITY_BOTTOM}, {@link #FLAG_HINT_GRAVITY_LEFT}, - * {@link #FLAG_HINT_GRAVITY_RIGHT}, {@link #FLAG_HOST_IME}, or - * {@link #FLAG_HOST_SYSTEM}, - */ - public @Flags int getFlags() { - return 0; - } - - /** @hide */ - void dump(@NonNull String prefix, @NonNull PrintWriter pw) { - final int flags = getFlags(); - if (flags > 0) { - pw.print(prefix); pw.print("flags: "); pw.println(flagsToString(flags)); - } - } - - private static String flagsToString(int flags) { - return DebugUtils.flagsToString(PresentationParams.class, "FLAG_", flags); - } + abstract void dump(String prefix, PrintWriter pw); /** * Area associated with a {@link PresentationParams Smart Suggestions} provider. @@ -154,8 +62,6 @@ public abstract class PresentationParams { */ @SystemApi @TestApi - //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service - //in the same package as the test, and that module is compiled with SDK=test_current public abstract static class Area { /** @hide */ @@ -176,24 +82,6 @@ public abstract class PresentationParams { return mBounds; } - /** - * Gets a subarea limited by given boundaries. - * - * @param bounds boundaries relative to this Area. - * - * @return new subarea, or {@code null} if the Smart Suggestion host does not support such - * subaarea. - * - * @throws IllegalArgumentException if the {@code bounds} is not fully-contained inside this - * full Area. - * - */ - @Nullable - public Area getSubArea(@NonNull Rect bounds) { - // TODO(b/123100712): implement / check boundaries / throw IAE / add unit test - return null; - } - @Override public String toString() { return mBounds.toString(); @@ -220,13 +108,7 @@ public abstract class PresentationParams { } @Override - public int getFlags() { - return FLAG_HOST_SYSTEM | FLAG_HINT_GRAVITY_BOTTOM; - } - - @Override void dump(@NonNull String prefix, @NonNull PrintWriter pw) { - super.dump(prefix, pw); pw.print(prefix); pw.print("area: "); pw.println(mSuggestionArea); } } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 5e5c8265f782..f93ac4ce7d16 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1782,10 +1782,6 @@ public final class AutofillManager { /** * Explicitly limits augmented autofill to the given packages and activities. * - * <p>When the whitelist is set, it overrides the values passed to - * {@link #setActivityAugmentedAutofillEnabled(ComponentName, boolean)} - * and {@link #setPackageAugmentedAutofillEnabled(String, boolean)}. - * * <p>To reset the whitelist, call it passing {@code null} to both arguments. * * <p>Useful when the service wants to restrict augmented autofill to a category of apps, like @@ -1803,8 +1799,6 @@ public final class AutofillManager { */ @SystemApi @TestApi - //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service - //in the same package as the test, and that module is compiled with SDK=test_current public void setAugmentedAutofillWhitelist(@Nullable List<String> packages, @Nullable List<ComponentName> activities) { // TODO(b/123100824): implement diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 8ebcef5133b6..585a1f1da417 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -633,40 +633,46 @@ public class ChooserActivity extends ResolverActivity { // due to permissions issues findViewById(R.id.file_copy_button).setVisibility(View.GONE); - ContentResolver resolver = getContentResolver(); - TextView fileNameView = findViewById(R.id.content_preview_filename); - String action = targetIntent.getAction(); - if (Intent.ACTION_SEND.equals(action)) { - Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); + try { + ContentResolver resolver = getContentResolver(); + TextView fileNameView = findViewById(R.id.content_preview_filename); + String action = targetIntent.getAction(); + if (Intent.ACTION_SEND.equals(action)) { + Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); - FileInfo fileInfo = extractFileInfo(uri, resolver); - fileNameView.setText(fileInfo.name); + FileInfo fileInfo = extractFileInfo(uri, resolver); + fileNameView.setText(fileInfo.name); - if (fileInfo.hasThumbnail) { - loadUriIntoView(R.id.content_preview_file_thumbnail, uri); + if (fileInfo.hasThumbnail) { + loadUriIntoView(R.id.content_preview_file_thumbnail, uri); + } else { + ImageView fileIconView = findViewById(R.id.content_preview_file_icon); + fileIconView.setVisibility(View.VISIBLE); + fileIconView.setImageResource(R.drawable.ic_doc_generic); + } } else { + List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); + if (uris.size() == 0) { + contentPreviewLayout.setVisibility(View.GONE); + Log.i(TAG, + "Appears to be no uris available in EXTRA_STREAM, removing preview " + + "area"); + return; + } + + FileInfo fileInfo = extractFileInfo(uris.get(0), resolver); + int remFileCount = uris.size() - 1; + String fileName = getResources().getQuantityString(R.plurals.file_count, + remFileCount, fileInfo.name, remFileCount); + + fileNameView.setText(fileName); ImageView fileIconView = findViewById(R.id.content_preview_file_icon); fileIconView.setVisibility(View.VISIBLE); - fileIconView.setImageResource(R.drawable.ic_doc_generic); + fileIconView.setImageResource(R.drawable.ic_file_copy); } - } else { - List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); - if (uris.size() == 0) { - contentPreviewLayout.setVisibility(View.GONE); - Log.i(TAG, - "Appears to be no uris available in EXTRA_STREAM, removing preview area"); - return; - } - - FileInfo fileInfo = extractFileInfo(uris.get(0), resolver); - int remFileCount = uris.size() - 1; - String fileName = getResources().getQuantityString(R.plurals.file_count, - remFileCount, fileInfo.name, remFileCount); - - fileNameView.setText(fileName); - ImageView fileIconView = findViewById(R.id.content_preview_file_icon); - fileIconView.setVisibility(View.VISIBLE); - fileIconView.setImageResource(R.drawable.ic_file_copy); + } catch (SecurityException e) { + Log.w(TAG, "Error loading file preview", e); + contentPreviewLayout.setVisibility(View.GONE); } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 52e1748c621c..4ff99482feff 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -187,6 +187,8 @@ public class BatteryStatsImpl extends BatteryStats { static final int MSG_REPORT_RESET_STATS = 4; static final long DELAY_UPDATE_WAKELOCKS = 5*1000; + private static final double MILLISECONDS_IN_HOUR = 3600 * 1000; + private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader(); private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats(); @@ -252,6 +254,9 @@ public class BatteryStatsImpl extends BatteryStats { private static final long RPM_STATS_UPDATE_FREQ_MS = 1000; /** Last time that RPM stats were updated by updateRpmStatsLocked. */ private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS; + + /** Container for Rail Energy Data stats. */ + private final RailStats mTmpRailStats = new RailStats(); /** * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader}, * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader}, @@ -327,6 +332,15 @@ public class BatteryStatsImpl extends BatteryStats { public String getSubsystemLowPowerStats(); } + /** interface to update rail information for power monitor */ + public interface RailEnergyDataCallback { + /** Function to fill the map for the rail data stats + * Used for power monitoring feature + * @param railStats + */ + void fillRailDataStats(RailStats railStats); + } + public static abstract class UserInfoProvider { private int[] userIds; protected abstract @Nullable int[] getUserIds(); @@ -361,6 +375,8 @@ public class BatteryStatsImpl extends BatteryStats { } }; + public final RailEnergyDataCallback mRailEnergyDataCallback; + /** * This handler is running on {@link BackgroundThread}. */ @@ -593,7 +609,9 @@ public class BatteryStatsImpl extends BatteryStats { int UPDATE_RADIO = 0x04; int UPDATE_BT = 0x08; int UPDATE_RPM = 0x10; // 16 - int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM; + int UPDATE_RAIL = 0x20; // 32 + int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM + | UPDATE_RAIL; Future<?> scheduleSync(String reason, int flags); Future<?> scheduleCpuSyncDueToRemovedUid(int uid); @@ -1078,6 +1096,7 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryStatsHistory = null; mHandler = null; mPlatformIdleStateCallback = null; + mRailEnergyDataCallback = null; mUserInfoProvider = null; mConstants = new Constants(mHandler); clearHistoryLocked(); @@ -3005,6 +3024,7 @@ public class BatteryStatsImpl extends BatteryStats { private final LongSamplingCounter mRxTimeMillis; private final LongSamplingCounter[] mTxTimeMillis; private final LongSamplingCounter mPowerDrainMaMs; + private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs; public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) { mIdleTimeMillis = new LongSamplingCounter(timeBase); @@ -3016,6 +3036,7 @@ public class BatteryStatsImpl extends BatteryStats { mTxTimeMillis[i] = new LongSamplingCounter(timeBase); } mPowerDrainMaMs = new LongSamplingCounter(timeBase); + mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase); } public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) { @@ -3033,6 +3054,7 @@ public class BatteryStatsImpl extends BatteryStats { mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in); } mPowerDrainMaMs = new LongSamplingCounter(timeBase, in); + mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in); } public void readSummaryFromParcel(Parcel in) { @@ -3048,6 +3070,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.readSummaryFromParcelLocked(in); } mPowerDrainMaMs.readSummaryFromParcelLocked(in); + mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in); } @Override @@ -3065,6 +3088,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.writeSummaryFromParcelLocked(dest); } mPowerDrainMaMs.writeSummaryFromParcelLocked(dest); + mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest); } @Override @@ -3078,6 +3102,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.writeToParcel(dest); } mPowerDrainMaMs.writeToParcel(dest); + mMonitoredRailChargeConsumedMaMs.writeToParcel(dest); } public void reset(boolean detachIfReset) { @@ -3089,6 +3114,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.reset(detachIfReset); } mPowerDrainMaMs.reset(detachIfReset); + mMonitoredRailChargeConsumedMaMs.reset(detachIfReset); } public void detach() { @@ -3100,6 +3126,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.detach(); } mPowerDrainMaMs.detach(); + mMonitoredRailChargeConsumedMaMs.detach(); } /** @@ -3154,6 +3181,15 @@ public class BatteryStatsImpl extends BatteryStats { public LongSamplingCounter getPowerCounter() { return mPowerDrainMaMs; } + + /** + * @return a LongSamplingCounter, measuring actual monitored rail energy consumed + * milli-ampere milli-seconds (mAmS). + */ + @Override + public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() { + return mMonitoredRailChargeConsumedMaMs; + } } /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */ @@ -3497,6 +3533,8 @@ public class BatteryStatsImpl extends BatteryStats { if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh); dest.writeInt(cur.batteryChargeUAh); } + dest.writeDouble(cur.modemRailChargeMah); + dest.writeDouble(cur.wifiRailChargeMah); } private int buildBatteryLevelInt(HistoryItem h) { @@ -3747,6 +3785,8 @@ public class BatteryStatsImpl extends BatteryStats { if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) { cur.batteryChargeUAh = src.readInt(); } + cur.modemRailChargeMah = src.readDouble(); + cur.wifiRailChargeMah = src.readDouble(); } @Override @@ -10111,12 +10151,12 @@ public class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, - UserInfoProvider userInfoProvider) { - this(new SystemClocks(), systemDir, handler, cb, userInfoProvider); + RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider) { + this(new SystemClocks(), systemDir, handler, cb, railStatsCb, userInfoProvider); } private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, - PlatformIdleStateCallback cb, + PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider) { init(clocks); @@ -10218,6 +10258,7 @@ public class BatteryStatsImpl extends BatteryStats { clearHistoryLocked(); updateDailyDeadlineLocked(); mPlatformIdleStateCallback = cb; + mRailEnergyDataCallback = railStatsCb; mUserInfoProvider = userInfoProvider; } @@ -10238,6 +10279,7 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer); readFromParcel(p); mPlatformIdleStateCallback = null; + mRailEnergyDataCallback = null; } public void setPowerProfileLocked(PowerProfile profile) { @@ -10934,6 +10976,8 @@ public class BatteryStatsImpl extends BatteryStats { mWakeupReasonStats.clear(); } + mTmpRailStats.reset(); + mLastHistoryStepDetails = null; mLastStepCpuUserTime = mLastStepCpuSystemTime = 0; mCurStepCpuUserTime = mCurStepCpuSystemTime = 0; @@ -11321,6 +11365,16 @@ public class BatteryStatsImpl extends BatteryStats { mWifiActivity.getPowerCounter().addCountLocked( (long) (info.getControllerEnergyUsed() / opVolt)); } + // Converting uWs to mAms. + // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms + long monitoredRailChargeConsumedMaMs = + (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt); + mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked( + monitoredRailChargeConsumedMaMs); + mHistoryCur.wifiRailChargeMah += + (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); + addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + mTmpRailStats.resetWifiTotalEnergyUsed(); } } } @@ -11411,9 +11465,18 @@ public class BatteryStatsImpl extends BatteryStats { // We store the power drain as mAms. mModemActivity.getPowerCounter().addCountLocked((long) energyUsed); + // Converting uWs to mAms. + // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms + long monitoredRailChargeConsumedMaMs = + (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt); + mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked( + monitoredRailChargeConsumedMaMs); + mHistoryCur.modemRailChargeMah += + (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); + addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + mTmpRailStats.resetCellularTotalEnergyUsed(); } } - final long elapsedRealtimeMs = mClocks.elapsedRealtime(); long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000); @@ -11812,6 +11875,16 @@ public class BatteryStatsImpl extends BatteryStats { } /** + * Read and record Rail Energy data. + */ + public void updateRailStatsLocked() { + if (mRailEnergyDataCallback == null || !mTmpRailStats.isRailStatsAvailable()) { + return; + } + mRailEnergyDataCallback.fillRailDataStats(mTmpRailStats); + } + + /** * Read and distribute kernel wake lock use across apps. */ public void updateKernelWakelocksLocked() { @@ -12950,6 +13023,8 @@ public class BatteryStatsImpl extends BatteryStats { final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which); + final long monitoredRailChargeConsumedMaMs = + counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which); long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES]; for (int i = 0; i < timeInRatMs.length; i++) { timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000; @@ -12979,58 +13054,62 @@ public class BatteryStatsImpl extends BatteryStats { s.setTimeInRatMs(timeInRatMs); s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs); s.setTxTimeMs(txTimeMs); + s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs); return s; } - /*@hide */ - public WifiBatteryStats getWifiBatteryStats() { - WifiBatteryStats s = new WifiBatteryStats(); - final int which = STATS_SINCE_CHARGED; - final long rawRealTime = SystemClock.elapsedRealtime() * 1000; - final ControllerActivityCounter counter = getWifiControllerActivity(); - final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); - final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which); - final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); - final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which); - final long totalControllerActivityTimeMs - = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000; - final long sleepTimeMs - = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs); - final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which); - long numAppScanRequest = 0; - for (int i = 0; i < mUidStats.size(); i++) { - numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which); - } - long[] timeInStateMs = new long[NUM_WIFI_STATES]; - for (int i=0; i<NUM_WIFI_STATES; i++) { + /*@hide */ + public WifiBatteryStats getWifiBatteryStats() { + WifiBatteryStats s = new WifiBatteryStats(); + final int which = STATS_SINCE_CHARGED; + final long rawRealTime = SystemClock.elapsedRealtime() * 1000; + final ControllerActivityCounter counter = getWifiControllerActivity(); + final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); + final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which); + final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); + final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which); + final long totalControllerActivityTimeMs + = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000; + final long sleepTimeMs + = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs); + final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which); + final long monitoredRailChargeConsumedMaMs = + counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which); + long numAppScanRequest = 0; + for (int i = 0; i < mUidStats.size(); i++) { + numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which); + } + long[] timeInStateMs = new long[NUM_WIFI_STATES]; + for (int i=0; i<NUM_WIFI_STATES; i++) { timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000; - } - long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES]; - for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) { - timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000; - } - long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS]; - for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { - timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000; - } - s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000); - s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000); - s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which)); - s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which)); - s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which)); - s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which)); - s.setSleepTimeMs(sleepTimeMs); - s.setIdleTimeMs(idleTimeMs); - s.setRxTimeMs(rxTimeMs); - s.setTxTimeMs(txTimeMs); - s.setScanTimeMs(scanTimeMs); - s.setEnergyConsumedMaMs(energyConsumedMaMs); - s.setNumAppScanRequest(numAppScanRequest); - s.setTimeInStateMs(timeInStateMs); - s.setTimeInSupplicantStateMs(timeInSupplStateMs); - s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs); - return s; - } + } + long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES]; + for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) { + timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000; + } + long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS]; + for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { + timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000; + } + s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000); + s.setKernelActiveTimeMs(getWifiActiveTime(rawRealTime, which) / 1000); + s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which)); + s.setNumBytesTx(getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which)); + s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which)); + s.setNumBytesRx(getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which)); + s.setSleepTimeMs(sleepTimeMs); + s.setIdleTimeMs(idleTimeMs); + s.setRxTimeMs(rxTimeMs); + s.setTxTimeMs(txTimeMs); + s.setScanTimeMs(scanTimeMs); + s.setEnergyConsumedMaMs(energyConsumedMaMs); + s.setNumAppScanRequest(numAppScanRequest); + s.setTimeInStateMs(timeInStateMs); + s.setTimeInSupplicantStateMs(timeInSupplStateMs); + s.setTimeInRxSignalStrengthLevelMs(timeSignalStrengthTimeMs); + s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs); + return s; + } /*@hide */ public GpsBatteryStats getGpsBatteryStats() { diff --git a/core/java/com/android/internal/os/RailStats.java b/core/java/com/android/internal/os/RailStats.java new file mode 100644 index 000000000000..ff0083138b30 --- /dev/null +++ b/core/java/com/android/internal/os/RailStats.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.os; + +import android.util.ArrayMap; +import android.util.Slog; + +import java.util.Map; + +/** Rail Stats Power Monitoring Class */ +public final class RailStats { + private static final String TAG = "RailStats"; + + private static final String WIFI_SUBSYSTEM = "wifi"; + private static final String CELLULAR_SUBSYSTEM = "cellular"; + + private Map<Long, RailInfoData> mRailInfoData = new ArrayMap<>(); + + private long mCellularTotalEnergyUseduWs = 0; + private long mWifiTotalEnergyUseduWs = 0; + private boolean mRailStatsAvailability = true; + + /** Updates the rail data map of all power monitor rails being monitored + * Function is called from native side + * @param index + * @param railName + * @param subSystemName + * @param timestampSinceBootMs + * @param energyUsedSinceBootuWs + */ + public void updateRailData(long index, String railName, String subSystemName, + long timestampSinceBootMs, long energyUsedSinceBootuWs) { + if (!(subSystemName.equals(WIFI_SUBSYSTEM) || subSystemName.equals(CELLULAR_SUBSYSTEM))) { + return; + } + RailInfoData node = mRailInfoData.get(index); + if (node == null) { + mRailInfoData.put(index, new RailInfoData(index, railName, subSystemName, + timestampSinceBootMs, energyUsedSinceBootuWs)); + if (subSystemName.equals(WIFI_SUBSYSTEM)) { + mWifiTotalEnergyUseduWs += energyUsedSinceBootuWs; + return; + } + if (subSystemName.equals(CELLULAR_SUBSYSTEM)) { + mCellularTotalEnergyUseduWs += energyUsedSinceBootuWs; + } + return; + } + long timeSinceLastLogMs = timestampSinceBootMs - node.timestampSinceBootMs; + long energyUsedSinceLastLoguWs = energyUsedSinceBootuWs - node.energyUsedSinceBootuWs; + if (timeSinceLastLogMs < 0 || energyUsedSinceLastLoguWs < 0) { + energyUsedSinceLastLoguWs = node.energyUsedSinceBootuWs; + } + node.timestampSinceBootMs = timestampSinceBootMs; + node.energyUsedSinceBootuWs = energyUsedSinceBootuWs; + if (subSystemName.equals(WIFI_SUBSYSTEM)) { + mWifiTotalEnergyUseduWs += energyUsedSinceLastLoguWs; + return; + } + if (subSystemName.equals(CELLULAR_SUBSYSTEM)) { + mCellularTotalEnergyUseduWs += energyUsedSinceLastLoguWs; + } + } + + /** resets the cellular total energy used aspect. + */ + public void resetCellularTotalEnergyUsed() { + mCellularTotalEnergyUseduWs = 0; + } + + /** resets the wifi total energy used aspect. + */ + public void resetWifiTotalEnergyUsed() { + mWifiTotalEnergyUseduWs = 0; + } + + public long getCellularTotalEnergyUseduWs() { + return mCellularTotalEnergyUseduWs; + } + + public long getWifiTotalEnergyUseduWs() { + return mWifiTotalEnergyUseduWs; + } + + /** reset the total energy subsystems + * + */ + public void reset() { + mCellularTotalEnergyUseduWs = 0; + mWifiTotalEnergyUseduWs = 0; + } + + public RailStats getRailStats() { + return this; + } + + public void setRailStatsAvailability(boolean railStatsAvailability) { + mRailStatsAvailability = railStatsAvailability; + } + + public boolean isRailStatsAvailable() { + return mRailStatsAvailability; + } + + /** Container class to contain rail data information */ + public static class RailInfoData { + private static final String TAG = "RailInfoData"; + public long index; + public String railName; + public String subSystemName; + public long timestampSinceBootMs; + public long energyUsedSinceBootuWs; + + private RailInfoData(long index, String railName, String subSystemName, + long timestampSinceBootMs, long energyUsedSinceBoot) { + this.index = index; + this.railName = railName; + this.subSystemName = subSystemName; + this.timestampSinceBootMs = timestampSinceBootMs; + this.energyUsedSinceBootuWs = energyUsedSinceBoot; + } + + /** print the rail data + * + */ + public void printData() { + Slog.d(TAG, "Index = " + index); + Slog.d(TAG, "RailName = " + railName); + Slog.d(TAG, "SubSystemName = " + subSystemName); + Slog.d(TAG, "TimestampSinceBootMs = " + timestampSinceBootMs); + Slog.d(TAG, "EnergyUsedSinceBootuWs = " + energyUsedSinceBootuWs); + } + } +} diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index e8172172f5d2..8f007594dd67 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -355,9 +355,16 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, colorType = kN32_SkColorType; } + sk_sp<SkColorSpace> colorSpace; + if (colorType == kAlpha_8_SkColorType) { + colorSpace = nullptr; + } else { + colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr); + } + SkBitmap bitmap; bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType, - GraphicsJNI::getNativeColorSpace(colorSpacePtr))); + colorSpace)); sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap); if (!nativeBitmap) { @@ -385,15 +392,17 @@ static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src, case kRGB_565_SkColorType: dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType); break; - case kRGBA_F16_SkColorType: - // The caller does not have an opportunity to pass a dst color space. Assume that - // they want linear sRGB. - dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear()); + case kAlpha_8_SkColorType: + dstInfo = dstInfo.makeColorSpace(nullptr); break; default: break; } + if (!dstInfo.colorSpace() && dstCT != kAlpha_8_SkColorType) { + dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB()); + } + if (!dst->setInfo(dstInfo)) { return false; } @@ -608,14 +617,6 @@ static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) { return static_cast<jint>(bitmap->getGenerationID()); } -static jboolean Bitmap_isConfigF16(JNIEnv* env, jobject, jlong bitmapHandle) { - LocalScopedBitmap bitmap(bitmapHandle); - if (bitmap->info().colorType() == kRGBA_F16_SkColorType) { - return JNI_TRUE; - } - return JNI_FALSE; -} - static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) { LocalScopedBitmap bitmap(bitmapHandle); if (bitmap->info().alphaType() == kPremul_SkAlphaType) { @@ -684,9 +685,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { const SkAlphaType alphaType = (SkAlphaType)p->readInt32(); const uint32_t colorSpaceSize = p->readUint32(); sk_sp<SkColorSpace> colorSpace; - if (kRGBA_F16_SkColorType == colorType) { - colorSpace = SkColorSpace::MakeSRGBLinear(); - } else if (colorSpaceSize > 0) { + if (colorSpaceSize > 0) { if (colorSpaceSize > kMaxColorSpaceSerializedBytes) { ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: " "%d bytes\n", colorSpaceSize); @@ -811,7 +810,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, p->writeInt32(bitmap.colorType()); p->writeInt32(bitmap.alphaType()); SkColorSpace* colorSpace = bitmap.colorSpace(); - if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) { + if (colorSpace != nullptr) { sk_sp<SkData> data = colorSpace->serialize(); size_t size = data->size(); p->writeUint32(size); @@ -924,44 +923,14 @@ static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) { return colorSpace == srgbLinear.get() ? JNI_TRUE : JNI_FALSE; } -static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, - jfloatArray xyzArray, jfloatArray paramsArray) { - +static jobject Bitmap_computeColorSpace(JNIEnv* env, jobject, jlong bitmapHandle) { LocalScopedBitmap bitmapHolder(bitmapHandle); - if (!bitmapHolder.valid()) return JNI_FALSE; + if (!bitmapHolder.valid()) return nullptr; SkColorSpace* colorSpace = bitmapHolder->info().colorSpace(); - if (colorSpace == nullptr) return JNI_FALSE; - - skcms_Matrix3x3 xyzMatrix; - if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE; - - jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL); - xyz[0] = xyzMatrix.vals[0][0]; - xyz[1] = xyzMatrix.vals[1][0]; - xyz[2] = xyzMatrix.vals[2][0]; - xyz[3] = xyzMatrix.vals[0][1]; - xyz[4] = xyzMatrix.vals[1][1]; - xyz[5] = xyzMatrix.vals[2][1]; - xyz[6] = xyzMatrix.vals[0][2]; - xyz[7] = xyzMatrix.vals[1][2]; - xyz[8] = xyzMatrix.vals[2][2]; - env->ReleaseFloatArrayElements(xyzArray, xyz, 0); - - skcms_TransferFunction transferParams; - if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE; - - jfloat* params = env->GetFloatArrayElements(paramsArray, NULL); - params[0] = transferParams.a; - params[1] = transferParams.b; - params[2] = transferParams.c; - params[3] = transferParams.d; - params[4] = transferParams.e; - params[5] = transferParams.f; - params[6] = transferParams.g; - env->ReleaseFloatArrayElements(paramsArray, params, 0); + if (colorSpace == nullptr) return nullptr; - return JNI_TRUE; + return GraphicsJNI::getColorSpace(env, colorSpace, bitmapHolder->info().colorType()); } static void Bitmap_setColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpacePtr) { @@ -1174,13 +1143,6 @@ static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitm return createJavaGraphicBuffer(env, buffer); } -static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlong dstBitmapPtr) { - LocalScopedBitmap srcBitmapHandle(srcBitmapPtr); - LocalScopedBitmap dstBitmapHandle(dstBitmapPtr); - - dstBitmapHandle->bitmap().setColorSpace(srcBitmapHandle->bitmap().info().refColorSpace()); -} - static jboolean Bitmap_isImmutable(jlong bitmapHandle) { LocalScopedBitmap bitmapHolder(bitmapHandle); if (!bitmapHolder.valid()) return JNI_FALSE; @@ -1215,7 +1177,6 @@ static const JNINativeMethod gBitmapMethods[] = { { "nativeErase", "(JJJ)V", (void*)Bitmap_eraseLong }, { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes }, { "nativeConfig", "(J)I", (void*)Bitmap_config }, - { "nativeIsConfigF16", "(J)Z", (void*)Bitmap_isConfigF16 }, { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha }, { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied}, { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha}, @@ -1248,12 +1209,10 @@ static const JNINativeMethod gBitmapMethods[] = { (void*) Bitmap_wrapHardwareBufferBitmap }, { "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;", (void*) Bitmap_createGraphicBufferHandle }, - { "nativeGetColorSpace", "(J[F[F)Z", (void*)Bitmap_getColorSpace }, + { "nativeComputeColorSpace", "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace }, { "nativeSetColorSpace", "(JJ)V", (void*)Bitmap_setColorSpace }, { "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB }, { "nativeIsSRGBLinear", "(J)Z", (void*)Bitmap_isSRGBLinear}, - { "nativeCopyColorSpace", "(JJ)V", - (void*)Bitmap_copyColorSpace }, { "nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable}, // ------------ @CriticalNative ---------------- diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 70e6604fddeb..4ba4540f7dbc 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -307,7 +307,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, env->SetObjectField(options, gOptions_outConfigFieldID, config); env->SetObjectField(options, gOptions_outColorSpaceFieldID, - GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType)); + GraphicsJNI::getColorSpace(env, decodeColorSpace.get(), decodeColorType)); if (onlyDecodeSize) { return nullptr; diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index d65f324d1065..9c07e2d64c6e 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -215,7 +215,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in env->SetObjectField(options, gOptions_outConfigFieldID, config); env->SetObjectField(options, gOptions_outColorSpaceFieldID, - GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType)); + GraphicsJNI::getColorSpace(env, decodeColorSpace.get(), decodeColorType)); } // If we may have reused a bitmap, we need to indicate that the pixels have changed. diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 6570992b4b23..2987c5ed56b5 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -187,6 +187,8 @@ static jmethodID gColorSpaceRGB_constructorMethodID; static jclass gColorSpace_Named_class; static jfieldID gColorSpace_Named_sRGBFieldID; +static jfieldID gColorSpace_Named_ExtendedSRGBFieldID; +static jfieldID gColorSpace_Named_LinearSRGBFieldID; static jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID; static jclass gTransferParameters_class; @@ -412,67 +414,78 @@ jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region) /////////////////////////////////////////////////////////////////////////////// -jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace, +jobject GraphicsJNI::getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace, SkColorType decodeColorType) { - jobject colorSpace = nullptr; + if (!decodeColorSpace || decodeColorType == kAlpha_8_SkColorType) { + return nullptr; + } - // No need to match, we know what the output color space will be + // Special checks for the common sRGB cases and their extended variants. + jobject namedCS = nullptr; + sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear(); if (decodeColorType == kRGBA_F16_SkColorType) { - jobject linearExtendedSRGB = env->GetStaticObjectField( - gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID); - colorSpace = env->CallStaticObjectMethod(gColorSpace_class, - gColorSpace_getMethodID, linearExtendedSRGB); - } else { - // Same here, no need to match + // An F16 Bitmap will always report that it is EXTENDED if + // it matches a ColorSpace that has an EXTENDED variant. if (decodeColorSpace->isSRGB()) { - jobject sRGB = env->GetStaticObjectField( - gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID); - colorSpace = env->CallStaticObjectMethod(gColorSpace_class, - gColorSpace_getMethodID, sRGB); - } else if (decodeColorSpace.get() != nullptr) { - // Try to match against known RGB color spaces using the CIE XYZ D50 - // conversion matrix and numerical transfer function parameters - skcms_Matrix3x3 xyzMatrix; - LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix)); - - skcms_TransferFunction transferParams; - // We can only handle numerical transfer functions at the moment - LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams)); - - jobject params = env->NewObject(gTransferParameters_class, - gTransferParameters_constructorMethodID, - transferParams.a, transferParams.b, transferParams.c, - transferParams.d, transferParams.e, transferParams.f, - transferParams.g); - - jfloatArray xyzArray = env->NewFloatArray(9); - jfloat xyz[9] = { - xyzMatrix.vals[0][0], - xyzMatrix.vals[1][0], - xyzMatrix.vals[2][0], - xyzMatrix.vals[0][1], - xyzMatrix.vals[1][1], - xyzMatrix.vals[2][1], - xyzMatrix.vals[0][2], - xyzMatrix.vals[1][2], - xyzMatrix.vals[2][2] - }; - env->SetFloatArrayRegion(xyzArray, 0, 9, xyz); - - colorSpace = env->CallStaticObjectMethod(gColorSpace_class, - gColorSpace_matchMethodID, xyzArray, params); - - if (colorSpace == nullptr) { - // We couldn't find an exact match, let's create a new color space - // instance with the 3x3 conversion matrix and transfer function - colorSpace = env->NewObject(gColorSpaceRGB_class, - gColorSpaceRGB_constructorMethodID, - env->NewStringUTF("Unknown"), xyzArray, params); - } - - env->DeleteLocalRef(xyzArray); + namedCS = env->GetStaticObjectField(gColorSpace_Named_class, + gColorSpace_Named_ExtendedSRGBFieldID); + } else if (decodeColorSpace == srgbLinear.get()) { + namedCS = env->GetStaticObjectField(gColorSpace_Named_class, + gColorSpace_Named_LinearExtendedSRGBFieldID); } + } else if (decodeColorSpace->isSRGB()) { + namedCS = env->GetStaticObjectField(gColorSpace_Named_class, + gColorSpace_Named_sRGBFieldID); + } else if (decodeColorSpace == srgbLinear.get()) { + namedCS = env->GetStaticObjectField(gColorSpace_Named_class, + gColorSpace_Named_LinearSRGBFieldID); + } + + if (namedCS) { + return env->CallStaticObjectMethod(gColorSpace_class, gColorSpace_getMethodID, namedCS); } + + // Try to match against known RGB color spaces using the CIE XYZ D50 + // conversion matrix and numerical transfer function parameters + skcms_Matrix3x3 xyzMatrix; + LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix)); + + skcms_TransferFunction transferParams; + // We can only handle numerical transfer functions at the moment + LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams)); + + jobject params = env->NewObject(gTransferParameters_class, + gTransferParameters_constructorMethodID, + transferParams.a, transferParams.b, transferParams.c, + transferParams.d, transferParams.e, transferParams.f, + transferParams.g); + + jfloatArray xyzArray = env->NewFloatArray(9); + jfloat xyz[9] = { + xyzMatrix.vals[0][0], + xyzMatrix.vals[1][0], + xyzMatrix.vals[2][0], + xyzMatrix.vals[0][1], + xyzMatrix.vals[1][1], + xyzMatrix.vals[2][1], + xyzMatrix.vals[0][2], + xyzMatrix.vals[1][2], + xyzMatrix.vals[2][2] + }; + env->SetFloatArrayRegion(xyzArray, 0, 9, xyz); + + jobject colorSpace = env->CallStaticObjectMethod(gColorSpace_class, + gColorSpace_matchMethodID, xyzArray, params); + + if (colorSpace == nullptr) { + // We couldn't find an exact match, let's create a new color space + // instance with the 3x3 conversion matrix and transfer function + colorSpace = env->NewObject(gColorSpaceRGB_class, + gColorSpaceRGB_constructorMethodID, + env->NewStringUTF("Unknown"), xyzArray, params); + } + + env->DeleteLocalRef(xyzArray); return colorSpace; } @@ -658,6 +671,10 @@ int register_android_graphics_Graphics(JNIEnv* env) FindClassOrDie(env, "android/graphics/ColorSpace$Named")); gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env, gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;"); + gColorSpace_Named_ExtendedSRGBFieldID = GetStaticFieldIDOrDie(env, + gColorSpace_Named_class, "EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;"); + gColorSpace_Named_LinearSRGBFieldID = GetStaticFieldIDOrDie(env, + gColorSpace_Named_class, "LINEAR_SRGB", "Landroid/graphics/ColorSpace$Named;"); gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env, gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;"); diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index dc0d022d94c0..f80651c30d64 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -109,7 +109,13 @@ public: */ static sk_sp<SkColorSpace> getNativeColorSpace(jlong colorSpaceHandle); - static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace, + /** + * Return the android.graphics.ColorSpace Java object that corresponds to decodeColorSpace + * and decodeColorType. + * + * This may create a new object if none of the Named ColorSpaces match. + */ + static jobject getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace, SkColorType decodeColorType); /** diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp index 2d83ac320733..9efcace06be3 100644 --- a/core/jni/android/graphics/ImageDecoder.cpp +++ b/core/jni/android/graphics/ImageDecoder.cpp @@ -506,9 +506,9 @@ static jstring ImageDecoder_nGetMimeType(JNIEnv* env, jobject /*clazz*/, jlong n static jobject ImageDecoder_nGetColorSpace(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) { auto* codec = reinterpret_cast<ImageDecoder*>(nativePtr)->mCodec.get(); - auto colorType = codec->computeOutputColorType(codec->getInfo().colorType()); + auto colorType = codec->computeOutputColorType(kN32_SkColorType); sk_sp<SkColorSpace> colorSpace = codec->computeOutputColorSpace(colorType); - return GraphicsJNI::getColorSpace(env, colorSpace, colorType); + return GraphicsJNI::getColorSpace(env, colorSpace.get(), colorType); } static const JNINativeMethod gImageDecoderMethods[] = { diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index c208ce3276c6..5cecf66a593c 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -612,7 +612,7 @@ static void CreateDir(const std::string& dir, } } -static void CreatePkgSandboxTarget(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) { +static void CreatePkgSandbox(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) { // Create /mnt/user/0/package/<package-name> userid_t user_id = multiuser_get_user_id(uid); std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id); @@ -622,7 +622,7 @@ static void CreatePkgSandboxTarget(uid_t uid, const std::string& package_name, f CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn); StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str()); - CreateDir(pkg_sandbox_dir, 0755, uid, uid, fail_fn); + CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn); } static void BindMount(const std::string& sourceDir, const std::string& targetDir, @@ -642,98 +642,29 @@ static void MountPkgSpecificDir(const std::string& mntSourceRoot, fail_fn_t fail_fn) { std::string mntSourceDir = StringPrintf("%s/Android/%s/%s", mntSourceRoot.c_str(), dirName, packageName.c_str()); + CreateDir(mntSourceDir, 0755, uid, uid, fail_fn); std::string mntTargetDir = StringPrintf("%s/Android/%s/%s", mntTargetRoot.c_str(), dirName, packageName.c_str()); + CreateDir(mntTargetDir, 0755, uid, uid, fail_fn); BindMount(mntSourceDir, mntTargetDir, fail_fn); } -static void CreateSubDirs(int dirfd, const std::string& parentDirPath, - const std::vector<std::string>& subDirs, - fail_fn_t fail_fn) { - for (auto& dirName : subDirs) { - struct stat sb; - if (TEMP_FAILURE_RETRY(fstatat(dirfd, dirName.c_str(), &sb, 0)) == 0) { - if (S_ISDIR(sb.st_mode)) { - continue; - } else if (TEMP_FAILURE_RETRY(unlinkat(dirfd, dirName.c_str(), 0)) == -1) { - fail_fn(CREATE_ERROR("Failed to unlinkat on %s/%s: %s", - parentDirPath.c_str(), dirName.c_str(), strerror(errno))); - } - } else if (errno != ENOENT) { - fail_fn(CREATE_ERROR("Failed to fstatat on %s/%s: %s", - parentDirPath.c_str(), dirName.c_str(), strerror(errno))); - } - if (TEMP_FAILURE_RETRY(mkdirat(dirfd, dirName.c_str(), 0700)) == -1) { - fail_fn(CREATE_ERROR("Failed to mkdirat on %s/%s: %s", - parentDirPath.c_str(), dirName.c_str(), strerror(errno))); - } - } -} - -static void EnsurePkgSpecificDirs(const std::string& path, - const std::vector<std::string>& packageNames, - bool createSandboxDir, - fail_fn_t fail_fn) { - std::string androidDir = StringPrintf("%s/Android", path.c_str()); - android::base::unique_fd androidFd( - open(androidDir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)); - if (androidFd.get() < 0) { - if (errno == ENOENT || errno == ENOTDIR) { - if (errno == ENOTDIR && TEMP_FAILURE_RETRY(unlink(androidDir.c_str())) == -1) { - fail_fn(CREATE_ERROR("Failed to unlink %s: %s", - androidDir.c_str(), strerror(errno))); - } - if (TEMP_FAILURE_RETRY(mkdir(androidDir.c_str(), 0700)) == -1) { - fail_fn(CREATE_ERROR("Failed to mkdir %s: %s", - androidDir.c_str(), strerror(errno))); - } - androidFd.reset(open(androidDir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)); - } - if (androidFd.get() < 0) { - fail_fn(CREATE_ERROR("Failed to open %s: %s", androidDir.c_str(), strerror(errno))); - } - } - - std::vector<std::string> dataMediaObbDirs = {"data", "media", "obb"}; - if (createSandboxDir) { - dataMediaObbDirs.push_back("sandbox"); - } - CreateSubDirs(androidFd.get(), androidDir, dataMediaObbDirs, fail_fn); - if (createSandboxDir) { - dataMediaObbDirs.pop_back(); - } - for (auto& dirName : dataMediaObbDirs) { - std::string dataDir = StringPrintf("%s/%s", androidDir.c_str(), dirName.c_str()); - android::base::unique_fd dataFd( - openat(androidFd, dirName.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)); - if (dataFd.get() < 0) { - fail_fn(CREATE_ERROR("Failed to openat %s/%s: %s", - androidDir.c_str(), dirName.c_str(), strerror(errno))); - } - CreateSubDirs(dataFd.get(), dataDir, packageNames, fail_fn); - } -} - -static void CreatePkgSandboxSource(const std::string& sandboxSource, fail_fn_t fail_fn) { - - struct stat sb; - if (TEMP_FAILURE_RETRY(stat(sandboxSource.c_str(), &sb)) == 0) { - if (S_ISDIR(sb.st_mode)) { - return; - } else if (TEMP_FAILURE_RETRY(unlink(sandboxSource.c_str())) == -1) { - fail_fn(CREATE_ERROR("Failed to unlink %s: %s", - sandboxSource.c_str(), strerror(errno))); - } - } else if (errno != ENOENT) { - fail_fn(CREATE_ERROR("Failed to stat %s: %s", - sandboxSource.c_str(), strerror(errno))); +static void createPkgSpecificDirRoots(const std::string& parentDir, + bool createSandbox, + mode_t mode, uid_t uid, gid_t gid, + fail_fn_t fail_fn) { + std::string androidDir = StringPrintf("%s/Android", parentDir.c_str()); + CreateDir(androidDir, mode, uid, gid, fail_fn); + std::vector<std::string> dirs = {"data", "media", "obb"}; + if (createSandbox) { + dirs.push_back("sandbox"); } - if (TEMP_FAILURE_RETRY(mkdir(sandboxSource.c_str(), 0700)) == -1) { - fail_fn(CREATE_ERROR("Failed to mkdir %s: %s", - sandboxSource.c_str(), strerror(errno))); + for (auto& dir : dirs) { + std::string path = StringPrintf("%s/%s", androidDir.c_str(), dir.c_str()); + CreateDir(path, mode, uid, gid, fail_fn); } } @@ -749,21 +680,21 @@ static void PreparePkgSpecificDirs(const std::vector<std::string>& packageNames, StringAppendF(&mntTarget, "/%d", userId); } - if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) == -1) { + if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) < 0) { ALOGE("Can't access %s: %s", mntSource.c_str(), strerror(errno)); continue; } - // Ensure /mnt/runtime/write/emulated/0/Android/{data,media,obb} - EnsurePkgSpecificDirs(mntSource, packageNames, true, fail_fn); + // Create /mnt/runtime/write/emulated/0/Android/{data,media,obb,sandbox} + createPkgSpecificDirRoots(mntSource, true, 0700, AID_ROOT, AID_ROOT, fail_fn); std::string sandboxSource = StringPrintf("%s/Android/sandbox/%s", mntSource.c_str(), sandboxId.c_str()); - CreatePkgSandboxSource(sandboxSource, fail_fn); + CreateDir(sandboxSource, 0755, uid, uid, fail_fn); BindMount(sandboxSource, mntTarget, fail_fn); - // Ensure /storage/emulated/0/Android/{data,media,obb} - EnsurePkgSpecificDirs(mntTarget, packageNames, false, fail_fn); + // Create /storage/emulated/0/Android/{data,media,obb} + createPkgSpecificDirRoots(mntTarget, false, 0755, uid, uid, fail_fn); for (auto& package : packageNames) { MountPkgSpecificDir(mntSource, mntTarget, package, uid, "data", fail_fn); MountPkgSpecificDir(mntSource, mntTarget, package, uid, "media", fail_fn); @@ -844,14 +775,15 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode, userid_t user_id = multiuser_get_user_id(uid); std::string pkgSandboxDir = StringPrintf("/mnt/user/%d/package/%s", user_id, package_name.c_str()); + struct stat sb; bool sandboxAlreadyCreated = true; - if (TEMP_FAILURE_RETRY(access(pkgSandboxDir.c_str(), F_OK)) == -1) { + if (TEMP_FAILURE_RETRY(lstat(pkgSandboxDir.c_str(), &sb)) == -1) { if (errno == ENOENT) { ALOGD("Sandbox not yet created for %s", pkgSandboxDir.c_str()); sandboxAlreadyCreated = false; - CreatePkgSandboxTarget(uid, package_name, fail_fn); + CreatePkgSandbox(uid, package_name, fail_fn); } else { - fail_fn(CREATE_ERROR("Failed to access %s: %s", + fail_fn(CREATE_ERROR("Failed to lstat %s: %s", pkgSandboxDir.c_str(), strerror(errno))); } } @@ -862,7 +794,7 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode, pkgSandboxDir.c_str(), strerror(errno))); } - if (TEMP_FAILURE_RETRY(access("/storage/obb_mount", F_OK)) == 0) { + if (access("/storage/obb_mount", F_OK) == 0) { if (mount_mode != MOUNT_EXTERNAL_INSTALLER) { remove("/storage/obb_mount"); } diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto index a4167c187194..516fa7b9336b 100644 --- a/core/proto/android/os/batterystats.proto +++ b/core/proto/android/os/batterystats.proto @@ -58,6 +58,10 @@ message ControllerActivityProto { optional int64 duration_ms = 2; } repeated TxLevel tx = 4; + + // Total rail charge consumed by the monitored rails by the controller. The value may + // always be 0 if the device doesn't support monitored rail calculations. + optional double monitored_rail_charge_mah = 5; } message SystemProto { diff --git a/core/res/res/drawable/ic_qs_night_display_on.xml b/core/res/res/drawable/ic_qs_night_display_on.xml index 35907cc83fe0..a4755ee256e2 100644 --- a/core/res/res/drawable/ic_qs_night_display_on.xml +++ b/core/res/res/drawable/ic_qs_night_display_on.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2017 The Android Open Source Project + Copyright (C) 2019 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,14 +14,13 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="64dp" - android:height="64dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <group - android:translateX="-1.0"> - <path - android:pathData="M13,12c0,-3.57 2.2,-6.62 5.31,-7.87 0.89,-0.36 0.75,-1.69 -0.19,-1.9 -1.1,-0.24 -2.27,-0.3 -3.48,-0.14 -4.51,0.6 -8.12,4.31 -8.59,8.83C5.43,16.93 10.12,22 16,22c0.73,0 1.43,-0.08 2.12,-0.23 0.95,-0.21 1.1,-1.53 0.2,-1.9A8.471,8.471 0,0 1,13 12z" - android:fillColor="#FFF"/> - </group> -</vector>
\ No newline at end of file + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="#FFFFFF" + android:pathData="M6.28,4.81c0,0.16,0.01,0.32,0.02,0.48c0.38,6.58,5.83,12.03,12.41,12.41c0.16,0.01,0.32,0.02,0.47,0.02 c-1.58,1.2-3.53,1.88-5.56,1.88c-0.46,0-0.93-0.03-1.4-0.1c-3.96-0.58-7.13-3.75-7.71-7.71C4.13,9.24,4.8,6.75,6.28,4.81 M8.27,0.6 c-0.08,0-0.17,0.02-0.25,0.07c-3.8,2.2-6.2,6.56-5.49,11.4c0.7,4.82,4.59,8.7,9.4,9.4c0.57,0.08,1.13,0.12,1.69,0.12 c4.15,0,7.78-2.26,9.72-5.62c0.2-0.35-0.07-0.76-0.44-0.76c-0.05,0-0.1,0.01-0.15,0.02c-1.03,0.31-2.12,0.48-3.25,0.48 c-0.22,0-0.44-0.01-0.67-0.02C13.23,15.38,8.62,10.77,8.29,5.17C8.21,3.81,8.38,2.49,8.75,1.26C8.86,0.91,8.59,0.6,8.27,0.6 L8.27,0.6z" /> +</vector> + diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 18f0cae4733c..bdb63643f615 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -891,8 +891,10 @@ public final class Bitmap implements Parcelable { } } + ColorSpace cs = source.getColorSpace(); + if (m == null || m.isIdentity()) { - bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha()); + bitmap = createBitmap(null, neww, newh, newConfig, source.hasAlpha(), cs); paint = null; // not needed } else { final boolean transformed = !m.rectStaysRect(); @@ -906,9 +908,14 @@ public final class Bitmap implements Parcelable { if (transformed) { if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) { transformedConfig = Config.ARGB_8888; + if (cs == null) { + cs = ColorSpace.get(ColorSpace.Named.SRGB); + } } } - bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha()); + + bitmap = createBitmap(null, neww, newh, transformedConfig, + transformed || source.hasAlpha(), cs); paint = new Paint(); paint.setFilterBitmap(filter); @@ -917,8 +924,6 @@ public final class Bitmap implements Parcelable { } } - nativeCopyColorSpace(source.mNativePtr, bitmap.mNativePtr); - // The new bitmap was created from a known bitmap source so assume that // they use the same density bitmap.mDensity = source.mDensity; @@ -1000,10 +1005,10 @@ public final class Bitmap implements Parcelable { * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. - * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}, - * {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the - * config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} - * is assumed. + * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16} + * and {@link ColorSpace.Named#SRGB sRGB} or + * {@link ColorSpace.Named#LINEAR_SRGB Linear sRGB} is provided then the + * corresponding extended range variant is assumed. * * @throws IllegalArgumentException if the width or height are <= 0, if * Config is Config.HARDWARE (because hardware bitmaps are always @@ -1055,10 +1060,10 @@ public final class Bitmap implements Parcelable { * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. - * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}, - * {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the - * config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} - * is assumed. + * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16} + * and {@link ColorSpace.Named#SRGB sRGB} or + * {@link ColorSpace.Named#LINEAR_SRGB Linear sRGB} is provided then the + * corresponding extended range variant is assumed. * * @throws IllegalArgumentException if the width or height are <= 0, if * Config is Config.HARDWARE (because hardware bitmaps are always @@ -1075,22 +1080,12 @@ public final class Bitmap implements Parcelable { if (config == Config.HARDWARE) { throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE"); } - if (colorSpace == null) { + if (colorSpace == null && config != Config.ALPHA_8) { throw new IllegalArgumentException("can't create bitmap without a color space"); } - if (config != Config.ARGB_8888) { - if (config == Config.RGBA_F16) { - // FIXME: This should be LINEAR_EXTENDED_SRGB, but that would fail a CTS test. See - // b/120960866. SRGB matches the old (incorrect) behavior. - //colorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB); - colorSpace = ColorSpace.get(ColorSpace.Named.SRGB); - } else { - colorSpace = ColorSpace.get(ColorSpace.Named.SRGB); - } - } Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, - colorSpace.getNativeInstance()); + colorSpace == null ? 0 : colorSpace.getNativeInstance()); if (display != null) { bm.mDensity = display.densityDpi; @@ -1701,41 +1696,9 @@ public final class Bitmap implements Parcelable { @Nullable public final ColorSpace getColorSpace() { checkRecycled("getColorSpace called on a recycled bitmap"); - // Cache the color space retrieval since it can be fairly expensive if (mColorSpace == null) { - if (nativeIsConfigF16(mNativePtr)) { - // an F16 bitmaps is intended to always be linear extended, but due to - // inconsistencies in Bitmap.create() functions it is possible to have - // rendered into a bitmap in non-linear sRGB. - if (nativeIsSRGB(mNativePtr)) { - mColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB); - } else { - mColorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB); - } - } else if (nativeIsSRGB(mNativePtr)) { - mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB); - } else if (nativeIsSRGBLinear(mNativePtr)) { - mColorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_SRGB); - } else { - float[] xyz = new float[9]; - float[] params = new float[7]; - - boolean hasColorSpace = nativeGetColorSpace(mNativePtr, xyz, params); - if (hasColorSpace) { - ColorSpace.Rgb.TransferParameters parameters = - new ColorSpace.Rgb.TransferParameters( - params[0], params[1], params[2], - params[3], params[4], params[5], params[6]); - ColorSpace cs = ColorSpace.match(xyz, parameters); - if (cs != null) { - mColorSpace = cs; - } else { - mColorSpace = new ColorSpace.Rgb("Unknown", xyz, parameters); - } - } - } + mColorSpace = nativeComputeColorSpace(mNativePtr); } - return mColorSpace; } @@ -1749,6 +1712,9 @@ public final class Bitmap implements Parcelable { * components min/max values reduce the numerical range compared to the * previously assigned color space. * + * @throws IllegalArgumentException If the {@code Config} (returned by {@link #getConfig()}) + * is {@link Config#ALPHA_8}. + * * @param colorSpace to assign to the bitmap */ public void setColorSpace(@NonNull ColorSpace colorSpace) { @@ -1756,29 +1722,47 @@ public final class Bitmap implements Parcelable { if (colorSpace == null) { throw new IllegalArgumentException("The colorSpace cannot be set to null"); } - if (getColorSpace() != null) { - if (mColorSpace.getComponentCount() != colorSpace.getComponentCount()) { + + if (getConfig() == Config.ALPHA_8) { + throw new IllegalArgumentException("Cannot set a ColorSpace on ALPHA_8"); + } + + // Keep track of the old ColorSpace for comparison, and so we can reset it in case of an + // Exception. + final ColorSpace oldColorSpace = getColorSpace(); + nativeSetColorSpace(mNativePtr, colorSpace.getNativeInstance()); + + // This will update mColorSpace. It may not be the same as |colorSpace|, e.g. if we + // corrected it because the Bitmap is F16. + mColorSpace = null; + final ColorSpace newColorSpace = getColorSpace(); + + try { + if (oldColorSpace.getComponentCount() != newColorSpace.getComponentCount()) { throw new IllegalArgumentException("The new ColorSpace must have the same " + "component count as the current ColorSpace"); - } - for (int i = 0; i < mColorSpace.getComponentCount(); i++) { - if (mColorSpace.getMinValue(i) < colorSpace.getMinValue(i)) { - throw new IllegalArgumentException("The new ColorSpace cannot increase the " - + "minimum value for any of the components compared to the current " - + "ColorSpace. To perform this type of conversion create a new Bitmap " - + "in the desired ColorSpace and draw this Bitmap into it."); - } - if (mColorSpace.getMaxValue(i) > colorSpace.getMaxValue(i)) { - throw new IllegalArgumentException("The new ColorSpace cannot decrease the " - + "maximum value for any of the components compared to the current " - + "ColorSpace/ To perform this type of conversion create a new Bitmap" - + "in the desired ColorSpace and draw this Bitmap into it."); + } else { + for (int i = 0; i < oldColorSpace.getComponentCount(); i++) { + if (oldColorSpace.getMinValue(i) < newColorSpace.getMinValue(i)) { + throw new IllegalArgumentException("The new ColorSpace cannot increase the " + + "minimum value for any of the components compared to the current " + + "ColorSpace. To perform this type of conversion create a new " + + "Bitmap in the desired ColorSpace and draw this Bitmap into it."); + } + if (oldColorSpace.getMaxValue(i) > newColorSpace.getMaxValue(i)) { + throw new IllegalArgumentException("The new ColorSpace cannot decrease the " + + "maximum value for any of the components compared to the current " + + "ColorSpace/ To perform this type of conversion create a new " + + "Bitmap in the desired ColorSpace and draw this Bitmap into it."); + } } } + } catch (IllegalArgumentException e) { + // Undo the change to the ColorSpace. + mColorSpace = oldColorSpace; + nativeSetColorSpace(mNativePtr, mColorSpace.getNativeInstance()); + throw e; } - - nativeSetColorSpace(mNativePtr, colorSpace.getNativeInstance()); - mColorSpace = colorSpace; } /** @@ -2197,7 +2181,6 @@ public final class Bitmap implements Parcelable { private static native void nativeErase(long nativeBitmap, long colorSpacePtr, long color); private static native int nativeRowBytes(long nativeBitmap); private static native int nativeConfig(long nativeBitmap); - private static native boolean nativeIsConfigF16(long nativeBitmap); private static native int nativeGetPixel(long nativeBitmap, int x, int y); private static native long nativeGetColor(long nativeBitmap, int x, int y); @@ -2241,11 +2224,10 @@ public final class Bitmap implements Parcelable { private static native Bitmap nativeWrapHardwareBufferBitmap(HardwareBuffer buffer, long nativeColorSpace); private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap); - private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params); + private static native ColorSpace nativeComputeColorSpace(long nativePtr); private static native void nativeSetColorSpace(long nativePtr, long nativeColorSpace); private static native boolean nativeIsSRGB(long nativePtr); private static native boolean nativeIsSRGBLinear(long nativePtr); - private static native void nativeCopyColorSpace(long srcBitmap, long dstBitmap); private static native void nativeSetImmutable(long nativePtr); diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 7aff0414106a..49c3a3ba68b8 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -151,12 +151,9 @@ public class BitmapFactory { * the decoder will pick either the color space embedded in the image * or the color space best suited for the requested image configuration * (for instance {@link ColorSpace.Named#SRGB sRGB} for - * the {@link Bitmap.Config#ARGB_8888} configuration).</p> - * - * <p>{@link Bitmap.Config#RGBA_F16} always uses the - * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space). - * Bitmaps in other configurations without an embedded color space are - * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p> + * {@link Bitmap.Config#ARGB_8888} configuration and + * {@link ColorSpace.Named#EXTENDED_SRGB EXTENDED_SRGB} for + * {@link Bitmap.Config#RGBA_F16}).</p> * * <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are * currently supported. An <code>IllegalArgumentException</code> will diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index c9e46942a51a..0d5233880674 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -1475,7 +1475,7 @@ public abstract class ColorSpace { x -> absRcpResponse(x, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4), x -> absResponse(x, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4), -0.799f, 2.399f, - null, // FIXME: Use SRGB_TRANSFER_PARAMETERS + SRGB_TRANSFER_PARAMETERS, Named.EXTENDED_SRGB.ordinal() ); sNamedColorSpaces[Named.LINEAR_EXTENDED_SRGB.ordinal()] = new ColorSpace.Rgb( diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 466a5fc2a770..26c5080eead0 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -1556,12 +1556,9 @@ public final class ImageDecoder implements AutoCloseable { * decoder will pick either the color space embedded in the image or the * {@link ColorSpace} best suited for the requested image configuration * (for instance {@link ColorSpace.Named#SRGB sRGB} for the - * {@link Bitmap.Config#ARGB_8888} configuration).</p> - * - * <p>{@link Bitmap.Config#RGBA_F16} always uses the - * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space. - * Bitmaps in other configurations without an embedded color space are - * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p> + * {@link Bitmap.Config#ARGB_8888} configuration and + * {@link ColorSpace.Named#EXTENDED_SRGB EXTENDED_SRGB} for + * {@link Bitmap.Config#RGBA_F16}).</p> * * <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are * currently supported. An <code>IllegalArgumentException</code> will diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml index b673e4f3b081..dd124b713a72 100644 --- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml +++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml @@ -14,12 +14,19 @@ Copyright (C) 2017 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal" > + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?android:attr/colorControlNormal"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L11,14.41V22h1l5.71-5.71L13.41,12L17.71,7.71z M13,5.83 l1.88,1.88L13,9.59V5.83z M14.88,16.29L13,18.17v-3.76L14.88,16.29z" /> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M 5 10.5 C 5.82842712475 10.5 6.5 11.1715728753 6.5 12 C 6.5 12.8284271247 5.82842712475 13.5 5 13.5 C 4.17157287525 13.5 3.5 12.8284271247 3.5 12 C 3.5 11.1715728753 4.17157287525 10.5 5 10.5 Z" /> <path - android:pathData="M13.51,12l3.75,-3.74c0.41,-0.41 0.41,-1.07 0,-1.48l-4.47,-4.47 -0.03,-0.03a1.046,1.046 0,0 0,-1.76 0.76v6.44L6.95,5.43c-0.41,-0.41 -1.06,-0.41 -1.47,0s-0.41,1.06 0,1.47l5.09,5.1 -5.09,5.09c-0.41,0.41 -0.41,1.06 0,1.47s1.06,0.41 1.47,0L11,14.51v6.45a1.04,1.04 0,0 0,1.75 0.76l0.05,-0.05 4.46,-4.46c0.41,-0.41 0.41,-1.07 0,-1.48L13.51,12zM12.99,9.67v-4.3l2.15,2.15 -2.15,2.15zM12.99,18.62v-4.3l2.15,2.15 -2.15,2.15zM6.06,13.06c-0.59,0.59 -1.54,0.59 -2.12,0a1.49,1.49 0,0 1,0 -2.12,1.49 1.49,0 0,1 2.12,0c0.59,0.59 0.59,1.53 0,2.12zM20.06,10.94c0.59,0.59 0.59,1.54 0,2.12 -0.59,0.59 -1.54,0.59 -2.12,0a1.49,1.49 0,0 1,0 -2.12,1.49 1.49,0 0,1 2.12,0z" - android:fillColor="#FFFFFFFF" /> + android:fillColor="#FFFFFFFF" + android:pathData="M 19 10.5 C 19.8284271247 10.5 20.5 11.1715728753 20.5 12 C 20.5 12.8284271247 19.8284271247 13.5 19 13.5 C 18.1715728753 13.5 17.5 12.8284271247 17.5 12 C 17.5 11.1715728753 18.1715728753 10.5 19 10.5 Z" /> </vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml index 8cc6caa8abc8..220c63ccca6d 100644 --- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml +++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml @@ -14,12 +14,13 @@ Copyright (C) 2017 The Android Open Source Project limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="64dp" - android:height="64dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:tint="?android:attr/colorControlNormal"> + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?android:attr/colorControlNormal"> + <path android:fillColor="#FFFFFFFF" - android:pathData="M13.5,12l3.8,-3.7c0.4,-0.4 0.4,-1.1 0,-1.5l-4.5,-4.5c-0.4,-0.4 -1.1,-0.4 -1.5,0.1C11.1,2.5 11,2.8 11,3v6.4L6.9,5.4C6.5,5 5.9,5 5.5,5.4s-0.4,1.1 0,1.5l5.1,5.1l-5.1,5.1c-0.4,0.4 -0.4,1.1 0,1.5s1.1,0.4 1.5,0l4.1,-4V21c0,0.6 0.5,1 1,1c0.3,0 0.5,-0.1 0.7,-0.3l0.1,0l4.5,-4.5c0.4,-0.4 0.4,-1.1 0,-1.5L13.5,12zM13,9.7V5.4l2.1,2.2L13,9.7zM13,18.6v-4.3l2.1,2.2L13,18.6z"/> + android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L11,14.41V22h1l5.71-5.71L13.41,12L17.71,7.71z M13,5.83 l1.88,1.88L13,9.59V5.83z M14.88,16.29L13,18.17v-3.76L14.88,16.29z" /> </vector> diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane.xml b/packages/SystemUI/res/drawable/ic_signal_airplane.xml index 0a4d7526a55d..f708ed9cb8a6 100644 --- a/packages/SystemUI/res/drawable/ic_signal_airplane.xml +++ b/packages/SystemUI/res/drawable/ic_signal_airplane.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2017 The Android Open Source Project + Copyright (C) 2019 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,16 +15,12 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="48dp" - android:height="48dp" - android:viewportWidth="20.5" - android:viewportHeight="20.5"> - <group - android:translateX="1.75" - android:translateY="1.4"> - <path - android:pathData="M16.01,9.87l-6.24,-3.9v-4.7C9.77,0.57 9.21,0 8.5,0S7.23,0.57 7.23,1.28v4.7L0.99,9.88c-0.37,0.23 -0.6,0.64 -0.6,1.08v0.41c0,0.29 0.29,0.5 0.55,0.41l6.27,-1.97v4.7l-1.37,1.02c-0.21,0.16 -0.34,0.41 -0.34,0.68v0.57c0,0.15 0.12,0.23 0.27,0.2 1.67,-0.47 1.12,-0.31 2.73,-0.78 1.03,0.3 1.7,0.49 2.72,0.78 0.15,0.03 0.27,-0.06 0.27,-0.2v-0.57c0,-0.27 -0.13,-0.52 -0.34,-0.68l-1.37,-1.02v-4.7l6.27,1.97c0.28,0.09 0.55,-0.12 0.55,-0.41v-0.41c0.01,-0.45 -0.23,-0.87 -0.59,-1.09z" - android:fillColor="#FFF"/> - </group> -</vector> + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> +<path + android:fillColor="#FFFFFF" + android:pathData="M21,16v-2l-8-5V3.5C13,2.67,12.33,2,11.5,2S10,2.67,10,3.5V9l-8,5v2l8-2.5V19l-2,1.5V22l3.5-1l3.5,1v-1.5L13,19v-5.5L21,16z" /> +</vector> diff --git a/packages/SystemUI/res/layout-land/global_actions_grid.xml b/packages/SystemUI/res/layout-land/global_actions_grid.xml new file mode 100644 index 000000000000..911b661d48eb --- /dev/null +++ b/packages/SystemUI/res/layout-land/global_actions_grid.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="utf-8"?> +<com.android.systemui.globalactions.GlobalActionsGridLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@id/global_actions_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + android:clipToPadding="false" + android:theme="@style/qs_theme" + android:gravity="top|right" + android:clipChildren="false" +> + + <LinearLayout + android:layout_height="match_parent" + android:layout_width="wrap_content" + android:gravity="top|right" + android:padding="0dp" + android:orientation="vertical" + android:layoutDirection="ltr" + android:layout_marginRight="@dimen/global_actions_grid_container_bottom_margin" + > + <!-- Grid of action items --> + <com.android.systemui.globalactions.ListGridLayout + android:id="@android:id/list" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layoutDirection="ltr" + android:layout_marginTop="@dimen/global_actions_grid_side_margin" + android:translationZ="@dimen/global_actions_translate" + android:paddingLeft="@dimen/global_actions_grid_top_padding" + android:paddingRight="@dimen/global_actions_grid_bottom_padding" + android:paddingTop="@dimen/global_actions_grid_left_padding" + android:paddingBottom="@dimen/global_actions_grid_right_padding" + android:background="?android:attr/colorBackgroundFloating" + > + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layoutDirection="ltr" + android:orientation="horizontal" + /> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layoutDirection="ltr" + android:orientation="horizontal" + /> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layoutDirection="ltr" + android:orientation="horizontal" + /> + </com.android.systemui.globalactions.ListGridLayout> + + <!-- For separated items--> + <LinearLayout + android:id="@+id/separated_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/global_actions_grid_side_margin" + android:layout_marginBottom="@dimen/global_actions_grid_side_margin" + android:paddingTop="@dimen/global_actions_grid_left_padding" + android:paddingLeft="@dimen/global_actions_grid_top_padding" + android:paddingBottom="@dimen/global_actions_grid_right_padding" + android:paddingRight="@dimen/global_actions_grid_bottom_padding" + android:orientation="horizontal" + android:layoutDirection="ltr" + android:background="?android:attr/colorBackgroundFloating" + android:translationZ="@dimen/global_actions_translate" + /> + + </LinearLayout> + +</com.android.systemui.globalactions.GlobalActionsGridLayout> diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml new file mode 100644 index 000000000000..669be1b40567 --- /dev/null +++ b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="utf-8"?> +<com.android.systemui.globalactions.GlobalActionsGridLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@id/global_actions_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + android:clipToPadding="false" + android:theme="@style/qs_theme" + android:gravity="top|left" + android:clipChildren="false" +> + + <LinearLayout + android:layout_height="match_parent" + android:layout_width="wrap_content" + android:gravity="bottom|left" + android:padding="0dp" + android:orientation="vertical" + android:layout_marginLeft="@dimen/global_actions_grid_container_bottom_margin" + > + <!-- For separated items--> + <LinearLayout + android:id="@+id/separated_button" + android:layout_gravity="top|left" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/global_actions_grid_side_margin" + android:layout_marginBottom="@dimen/global_actions_grid_side_margin" + android:paddingTop="@dimen/global_actions_grid_left_padding" + android:paddingLeft="@dimen/global_actions_grid_top_padding" + android:paddingBottom="@dimen/global_actions_grid_right_padding" + android:paddingRight="@dimen/global_actions_grid_bottom_padding" + android:orientation="horizontal" + android:layoutDirection="rtl" + android:background="?android:attr/colorBackgroundFloating" + android:translationZ="@dimen/global_actions_translate" + /> + + <!-- Grid of action items --> + <com.android.systemui.globalactions.ListGridLayout + android:id="@android:id/list" + android:layout_gravity="bottom|left" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginTop="@dimen/global_actions_grid_side_margin" + android:translationZ="@dimen/global_actions_translate" + android:paddingLeft="@dimen/global_actions_grid_top_padding" + android:paddingRight="@dimen/global_actions_grid_bottom_padding" + android:paddingTop="@dimen/global_actions_grid_left_padding" + android:paddingBottom="@dimen/global_actions_grid_right_padding" + android:background="?android:attr/colorBackgroundFloating" + > + <LinearLayout + android:layout_gravity="bottom" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layoutDirection="rtl" + android:orientation="horizontal" + /> + <LinearLayout + android:layout_gravity="bottom" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layoutDirection="rtl" + android:orientation="horizontal" + /> + <LinearLayout + android:layout_gravity="bottom" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone" + android:layoutDirection="rtl" + android:orientation="horizontal" + /> + </com.android.systemui.globalactions.ListGridLayout> + </LinearLayout> + +</com.android.systemui.globalactions.GlobalActionsGridLayout> diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml index e6f2376ae76b..1b56fa089281 100644 --- a/packages/SystemUI/res/layout/global_actions_grid.xml +++ b/packages/SystemUI/res/layout/global_actions_grid.xml @@ -12,10 +12,11 @@ > <LinearLayout - android:layout_height="290dp" - android:layout_width="412dp" - android:gravity="bottom" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:gravity="bottom | right" android:padding="0dp" + android:layoutDirection="ltr" android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin" > <!-- For separated items--> @@ -34,15 +35,11 @@ android:translationZ="@dimen/global_actions_translate" /> - <Space android:layout_width="match_parent" android:layout_height="2dp" - android:layout_weight="1" /> - <!-- Grid of action items --> <com.android.systemui.globalactions.ListGridLayout android:id="@android:id/list" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="right" android:orientation="horizontal" android:layoutDirection="rtl" android:layout_marginRight="@dimen/global_actions_grid_side_margin" @@ -56,25 +53,19 @@ <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom|right" android:visibility="gone" - android:gravity="bottom" android:orientation="vertical" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom|right" android:visibility="gone" - android:gravity="bottom" android:orientation="vertical" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom|right" android:visibility="gone" - android:gravity="bottom" android:orientation="vertical" /> </com.android.systemui.globalactions.ListGridLayout> diff --git a/packages/SystemUI/res/layout/global_actions_grid_item.xml b/packages/SystemUI/res/layout/global_actions_grid_item.xml index 0c11cd977256..a8938390690f 100644 --- a/packages/SystemUI/res/layout/global_actions_grid_item.xml +++ b/packages/SystemUI/res/layout/global_actions_grid_item.xml @@ -47,6 +47,7 @@ android:gravity="center" android:textSize="12sp" android:textAppearance="?android:attr/textAppearanceSmall" + android:singleLine="true" /> <TextView @@ -57,5 +58,6 @@ android:gravity="center" android:textColor="?android:attr/textColorTertiary" android:textAppearance="?android:attr/textAppearanceSmall" + android:singleLine="true" /> </LinearLayout> diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java index e28aa9d369cb..2a1d066d356e 100644 --- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java +++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java @@ -23,7 +23,6 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; -import android.content.res.Configuration; import android.provider.Settings; import android.util.AttributeSet; import android.view.Gravity; @@ -59,7 +58,6 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable { private int mEndPoint; private boolean mEdgeBleed; private boolean mRoundedDivider; - private int mRotation = ROTATION_NONE; private boolean mRotatedBackground; private boolean mSwapOrientation = true; @@ -89,7 +87,7 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable { } @Override - public ViewGroup getParentView(boolean separated, int index) { + public ViewGroup getParentView(boolean separated, int index, boolean reverse) { if (separated) { return getSeparatedView(); } else { @@ -174,7 +172,6 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable { mSeparatedView.setBackground(mSeparatedViewBackground); updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding()); mOldHeight = mList.getMeasuredHeight(); - updateRotation(); } else { return; } @@ -188,25 +185,13 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable { post(() -> updatePosition()); } - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - updateRotation(); - } - public void setSwapOrientation(boolean swapOrientation) { mSwapOrientation = swapOrientation; } - private void updateRotation() { - int rotation = RotationUtils.getRotation(getContext()); - if (rotation != mRotation) { - rotate(mRotation, rotation); - mRotation = rotation; - } - } - - private void rotate(int from, int to) { + @Override + protected void rotate(int from, int to) { + super.rotate(from, to); if (from != ROTATION_NONE && to != ROTATION_NONE) { // Rather than handling this confusing case, just do 2 rotations. rotate(from, ROTATION_NONE); diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java index 85265f458370..00ff518ce212 100644 --- a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java +++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java @@ -17,11 +17,14 @@ package com.android.systemui; import android.content.Context; +import android.content.res.Configuration; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; +import com.android.systemui.util.leak.RotationUtils; + /** * Layout class representing the Global Actions menu which appears when the power button is held. */ @@ -32,8 +35,12 @@ public abstract class MultiListLayout extends LinearLayout { protected int mExpectedSeparatedItemCount; protected int mExpectedListItemCount; + protected int mRotation; + protected RotationListener mRotationListener; + public MultiListLayout(Context context, AttributeSet attrs) { super(context, attrs); + mRotation = RotationUtils.getRotation(context); } protected abstract ViewGroup getSeparatedView(); @@ -50,10 +57,12 @@ public abstract class MultiListLayout extends LinearLayout { * @param separated Whether or not this index refers to a position in the separated or list * container. * @param index The index of the item within the container. + * @param reverse If the MultiListLayout contains sub-lists within the list container, reverse + * the order that they are filled. * @return The parent ViewGroup which will be used to contain the specified item * after it has been added to the layout. */ - public abstract ViewGroup getParentView(boolean separated, int index); + public abstract ViewGroup getParentView(boolean separated, int index, boolean reverse); /** * Sets the divided view, which may have a differently-colored background. @@ -111,6 +120,26 @@ public abstract class MultiListLayout extends LinearLayout { setFocusable(true); } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + int newRotation = RotationUtils.getRotation(mContext); + if (newRotation != mRotation) { + rotate(mRotation, newRotation); + mRotation = newRotation; + } + } + + protected void rotate(int from, int to) { + if (mRotationListener != null) { + mRotationListener.onRotate(from, to); + } + } + + public void setRotationListener(RotationListener listener) { + mRotationListener = listener; + } + /** * Retrieve the MultiListLayout associated with the given view. */ @@ -121,4 +150,8 @@ public abstract class MultiListLayout extends LinearLayout { } return null; } + + interface RotationListener { + void onRotate(int from, int to); + } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index a67e1b7032c6..be2dd679bba5 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -150,7 +150,8 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe } @Inject - public BubbleController(Context context, StatusBarWindowController statusBarWindowController) { + public BubbleController(Context context, StatusBarWindowController statusBarWindowController, + BubbleData data) { mContext = context; mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); @@ -171,7 +172,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe mTaskStackListener = new BubbleTaskStackListener(); ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); - mBubbleData = BubbleData.getInstance(); + mBubbleData = data; } /** @@ -253,7 +254,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe mStackView.updateBubble(notif, updatePosition); } else { if (mStackView == null) { - mStackView = new BubbleStackView(mContext); + mStackView = new BubbleStackView(mContext, mBubbleData); ViewGroup sbv = mStatusBarWindowController.getStatusBarView(); // XXX: Bug when you expand the shade on top of expanded bubble, there is no scrim // between bubble and the shade diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 89b0de85e18d..5002f5cce751 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -22,23 +22,19 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.Collection; import java.util.HashMap; +import javax.inject.Inject; +import javax.inject.Singleton; + /** * Keeps track of active bubbles. */ +@Singleton class BubbleData { private HashMap<String, Bubble> mBubbles = new HashMap<>(); - private static BubbleData sBubbleData = null; - - private BubbleData() {} - - public static BubbleData getInstance() { - if (sBubbleData == null) { - sBubbleData = new BubbleData(); - } - return sBubbleData; - } + @Inject + BubbleData() {} /** * The set of bubbles. diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index 3389c46f66b7..492eadd240ed 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -107,8 +107,10 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList private ActivityView.StateCallback mStateCallback = new ActivityView.StateCallback() { @Override public void onActivityViewReady(ActivityView view) { - mActivityViewReady = true; - mActivityView.startActivity(mBubbleIntent); + if (!mActivityViewReady) { + mActivityViewReady = true; + mActivityView.startActivity(mBubbleIntent); + } } @Override @@ -262,6 +264,12 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList updateHeaderView(); updatePermissionView(); updateExpandedView(); + } + + /** + * Lets activity view know it should be shown / populated. + */ + public void populateActivityView() { mActivityView.setCallback(mStateCallback); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 8bc83d4c852b..62cc8895ac73 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -85,6 +85,7 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F private final SpringAnimation mExpandedViewXAnim; private final SpringAnimation mExpandedViewYAnim; + private final BubbleData mBubbleData; private PhysicsAnimationLayout mBubbleContainer; private StackAnimationController mStackAnimationController; @@ -92,12 +93,12 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F private FrameLayout mExpandedViewContainer; - private BubbleData mBubbleData; private int mBubbleSize; private int mBubblePadding; private int mExpandedAnimateXDistance; private int mExpandedAnimateYDistance; + private int mStatusBarHeight; private Bubble mExpandedBubble; private boolean mIsExpanded; @@ -140,10 +141,10 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F } }; - public BubbleStackView(Context context) { + public BubbleStackView(Context context, BubbleData data) { super(context); - mBubbleData = BubbleData.getInstance(); + mBubbleData = data; mInflater = LayoutInflater.from(context); mTouchHandler = new BubbleTouchHandler(context); setOnTouchListener(mTouchHandler); @@ -155,6 +156,8 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F res.getDimensionPixelSize(R.dimen.bubble_expanded_animate_x_distance); mExpandedAnimateYDistance = res.getDimensionPixelSize(R.dimen.bubble_expanded_animate_y_distance); + mStatusBarHeight = + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); mDisplaySize = new Point(); WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); @@ -678,7 +681,7 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F if (getRootWindowInsets() != null) { WindowInsets insets = getRootWindowInsets(); return Math.max( - insets.getSystemWindowInsetTop(), + mStatusBarHeight, insets.getDisplayCutout() != null ? insets.getDisplayCutout().getSafeInsetTop() : 0); @@ -707,6 +710,7 @@ public class BubbleStackView extends FrameLayout implements BubbleTouchHandler.F mExpandedViewContainer.removeAllViews(); if (mExpandedBubble != null && mIsExpanded) { mExpandedViewContainer.addView(mExpandedBubble.expandedView); + mExpandedBubble.expandedView.populateActivityView(); mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java index 164406494250..5b158e906356 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -16,6 +16,7 @@ package com.android.systemui.bubbles.animation; +import android.content.res.Resources; import android.graphics.PointF; import android.view.View; import android.view.WindowInsets; @@ -55,16 +56,19 @@ public class ExpandedAnimationController private float mBubblePaddingPx; /** Size of each bubble. */ private float mBubbleSizePx; + /** Height of the status bar. */ + private float mStatusBarHeight; @Override protected void setLayout(PhysicsAnimationLayout layout) { super.setLayout(layout); - mStackOffsetPx = layout.getResources().getDimensionPixelSize( - R.dimen.bubble_stack_offset); - mBubblePaddingPx = layout.getResources().getDimensionPixelSize( - R.dimen.bubble_padding); - mBubbleSizePx = layout.getResources().getDimensionPixelSize( - R.dimen.individual_bubble_size); + + final Resources res = layout.getResources(); + mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); + mBubblePaddingPx = res.getDimensionPixelSize(R.dimen.bubble_padding); + mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size); + mStatusBarHeight = + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); } /** @@ -103,7 +107,7 @@ public class ExpandedAnimationController final WindowInsets insets = mLayout.getRootWindowInsets(); if (insets != null) { return mBubblePaddingPx + Math.max( - insets.getSystemWindowInsetTop(), + mStatusBarHeight, insets.getDisplayCutout() != null ? insets.getDisplayCutout().getSafeInsetTop() : 0); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java index 0c089a75aece..7dfb21cf384f 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java @@ -16,15 +16,12 @@ package com.android.systemui.bubbles.animation; -import android.content.Context; import android.content.res.Resources; -import android.graphics.Point; import android.graphics.PointF; import android.graphics.RectF; import android.util.Log; import android.view.View; import android.view.WindowInsets; -import android.view.WindowManager; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.FlingAnimation; @@ -88,9 +85,8 @@ public class StackAnimationController extends private int mBubbleOffscreen; /** How far down the screen the stack starts, when there is no pre-existing location. */ private int mStackStartingVerticalOffset; - - private Point mDisplaySize; - private RectF mAllowableStackPositionRegion; + /** Height of the status bar. */ + private float mStatusBarHeight; @Override protected void setLayout(PhysicsAnimationLayout layout) { @@ -103,11 +99,8 @@ public class StackAnimationController extends mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen); mStackStartingVerticalOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y); - - mDisplaySize = new Point(); - WindowManager wm = - (WindowManager) layout.getContext().getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getSize(mDisplaySize); + mStatusBarHeight = + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); } /** @@ -203,10 +196,9 @@ public class StackAnimationController extends */ public RectF getAllowableStackPositionRegion() { final WindowInsets insets = mLayout.getRootWindowInsets(); - mAllowableStackPositionRegion = new RectF(); - + final RectF allowableRegion = new RectF(); if (insets != null) { - mAllowableStackPositionRegion.left = + allowableRegion.left = -mBubbleOffscreen - mBubblePadding + Math.max( @@ -214,7 +206,7 @@ public class StackAnimationController extends insets.getDisplayCutout() != null ? insets.getDisplayCutout().getSafeInsetLeft() : 0); - mAllowableStackPositionRegion.right = + allowableRegion.right = mLayout.getWidth() - mIndividualBubbleSize + mBubbleOffscreen @@ -222,17 +214,17 @@ public class StackAnimationController extends - Math.max( insets.getSystemWindowInsetRight(), insets.getDisplayCutout() != null - ? insets.getDisplayCutout().getSafeInsetRight() - : 0); + ? insets.getDisplayCutout().getSafeInsetRight() + : 0); - mAllowableStackPositionRegion.top = + allowableRegion.top = mBubblePadding + Math.max( - insets.getSystemWindowInsetTop(), + mStatusBarHeight, insets.getDisplayCutout() != null - ? insets.getDisplayCutout().getSafeInsetTop() - : 0); - mAllowableStackPositionRegion.bottom = + ? insets.getDisplayCutout().getSafeInsetTop() + : 0); + allowableRegion.bottom = mLayout.getHeight() - mIndividualBubbleSize - mBubblePadding @@ -243,7 +235,7 @@ public class StackAnimationController extends : 0); } - return mAllowableStackPositionRegion; + return allowableRegion; } @Override @@ -287,31 +279,14 @@ public class StackAnimationController extends @Override void onChildAdded(View child, int index) { - // If this is the first child added, position the stack in its starting position. if (mLayout.getChildCount() == 1) { - moveStackToStartPosition(); - } - - if (mLayout.indexOfChild(child) == 0) { - child.setTranslationY(mStackPosition.y); - - // Pop in the new bubble. - child.setScaleX(ANIMATE_IN_STARTING_SCALE); - child.setScaleY(ANIMATE_IN_STARTING_SCALE); - mLayout.animateValueForChildAtIndex(DynamicAnimation.SCALE_X, 0, 1f); - mLayout.animateValueForChildAtIndex(DynamicAnimation.SCALE_Y, 0, 1f); - - // Fade in the new bubble. - child.setAlpha(0); - mLayout.animateValueForChildAtIndex(DynamicAnimation.ALPHA, 0, 1f); - - // Start the new bubble 4x the normal offset distance in the opposite direction. We'll - // animate in from this position. Since the animations are chained, when the new bubble - // flies in from the side, it will push the other ones out of the way. - float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X); - child.setTranslationX(mStackPosition.x - ANIMATE_TRANSLATION_FACTOR * xOffset); - mLayout.animateValueForChildAtIndex( - DynamicAnimation.TRANSLATION_X, 0, mStackPosition.x); + // If this is the first child added, position the stack in its starting position before + // animating in. + moveStackToStartPosition(() -> animateInBubble(child)); + } else if (mLayout.indexOfChild(child) == 0) { + // Otherwise, animate the bubble in if it's the newest bubble. If we're adding a bubble + // to the back of the stack, it'll be largely invisible so don't bother animating it in. + animateInBubble(child); } } @@ -334,10 +309,14 @@ public class StackAnimationController extends } /** Moves the stack, without any animation, to the starting position. */ - private void moveStackToStartPosition() { - mLayout.post(() -> setStackPosition( - getAllowableStackPositionRegion().right, - getAllowableStackPositionRegion().top + mStackStartingVerticalOffset)); + private void moveStackToStartPosition(Runnable after) { + // Post to ensure that the layout's width and height have been calculated. + mLayout.post(() -> { + setStackPosition( + getAllowableStackPositionRegion().right, + getAllowableStackPositionRegion().top + mStackStartingVerticalOffset); + after.run(); + }); } /** @@ -379,6 +358,29 @@ public class StackAnimationController extends } } + /** Animates in the given bubble. */ + private void animateInBubble(View child) { + child.setTranslationY(mStackPosition.y); + + // Pop in the new bubble. + child.setScaleX(ANIMATE_IN_STARTING_SCALE); + child.setScaleY(ANIMATE_IN_STARTING_SCALE); + mLayout.animateValueForChildAtIndex(DynamicAnimation.SCALE_X, 0, 1f); + mLayout.animateValueForChildAtIndex(DynamicAnimation.SCALE_Y, 0, 1f); + + // Fade in the new bubble. + child.setAlpha(0); + mLayout.animateValueForChildAtIndex(DynamicAnimation.ALPHA, 0, 1f); + + // Start the new bubble 4x the normal offset distance in the opposite direction. We'll + // animate in from this position. Since the animations are chained, when the new bubble + // flies in from the side, it will push the other ones out of the way. + float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X); + child.setTranslationX(mStackPosition.x - ANIMATE_TRANSLATION_FACTOR * xOffset); + mLayout.animateValueForChildAtIndex( + DynamicAnimation.TRANSLATION_X, 0, mStackPosition.x); + } + /** * Springs the first bubble to the given final position, with the rest of the stack 'following'. */ diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index f5ac0d39d61f..7c9b2864f7f2 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -33,6 +33,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; +import android.content.res.Configuration; import android.database.ContentObserver; import android.graphics.Point; import android.graphics.drawable.Drawable; @@ -91,6 +92,7 @@ import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.EmergencyDialerConstants; +import com.android.systemui.util.leak.RotationUtils; import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator; import java.util.ArrayList; @@ -159,6 +161,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, private final ScreenshotHelper mScreenshotHelper; private final ScreenRecordHelper mScreenRecordHelper; + private int mLastRotation; + /** * @param context everything needs a context :( */ @@ -201,6 +205,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, mScreenshotHelper = new ScreenshotHelper(context); mScreenRecordHelper = new ScreenRecordHelper(context); + mLastRotation = RotationUtils.getRotation(mContext); + Dependency.get(ConfigurationController.class).addCallback(this); } @@ -426,6 +432,15 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, mContext.getTheme().applyStyle(mContext.getThemeResId(), true); } + @Override + public void onConfigChanged(Configuration newConfig) { + int rotation = RotationUtils.getRotation(mContext); + if (rotation != mLastRotation) { + mDialog.onRotate(); + } + mLastRotation = rotation; + } + public void destroy() { Dependency.get(ConfigurationController.class).removeCallback(this); } @@ -1091,7 +1106,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, } protected int getActionLayoutId(Context context) { - if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED)) { + if (isGridEnabled(context)) { return com.android.systemui.R.layout.global_actions_grid_item; } return com.android.systemui.R.layout.global_actions_item; @@ -1465,7 +1480,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, private final Context mContext; private final MyAdapter mAdapter; - private final MultiListLayout mGlobalActionsLayout; + private MultiListLayout mGlobalActionsLayout; private final OnClickListener mClickListener; private final OnItemLongClickListener mLongClickListener; private final GradientDrawable mGradientDrawable; @@ -1505,8 +1520,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, window.setBackgroundDrawable(mGradientDrawable); window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); + initializeLayout(); - setContentView(getGlobalActionsLayoutId(context)); + setTitle(R.string.global_actions); + } + + private void initializeLayout() { + setContentView(getGlobalActionsLayoutId(mContext)); mGlobalActionsLayout = (MultiListLayout) findViewById(com.android.systemui.R.id.global_actions_view); mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss()); @@ -1520,11 +1540,20 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, return true; } }); - setTitle(R.string.global_actions); + } + + public void onRotate() { + if (mShowing && isGridEnabled(mContext)) { + initializeLayout(); + updateList(); + } } private int getGlobalActionsLayoutId(Context context) { - if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED)) { + if (isGridEnabled(context)) { + if (RotationUtils.getRotation(context) == RotationUtils.ROTATION_SEASCAPE) { + return com.android.systemui.R.layout.global_actions_grid_seascape; + } return com.android.systemui.R.layout.global_actions_grid; } return com.android.systemui.R.layout.global_actions_wrapped; @@ -1543,10 +1572,20 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, int separatedIndex = separatedActions.indexOf(action); ViewGroup parent; if (separatedIndex != -1) { - parent = mGlobalActionsLayout.getParentView(true, separatedIndex); + parent = mGlobalActionsLayout.getParentView(true, separatedIndex, false); } else { + boolean reverse = false; + + // If we're using the grid layout and we're in seascape, reverse the order + // of sublists to make sure they render in the correct positions, + // since we can't reverse vertical LinearLayouts through the layout xml. + + if (isGridEnabled(mContext) && RotationUtils.getRotation(mContext) + == RotationUtils.ROTATION_SEASCAPE) { + reverse = true; + } int listIndex = listActions.indexOf(action); - parent = mGlobalActionsLayout.getParentView(false, listIndex); + parent = mGlobalActionsLayout.getParentView(false, listIndex, reverse); } View v = mAdapter.getView(i, null, parent); final int pos = i; @@ -1665,4 +1704,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, mKeyguardShowing = keyguardShowing; } } + + /** + * Determines whether or not the Global Actions Dialog should use the newer grid-style layout. + */ + public static boolean isGridEnabled(Context context) { + return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED); + } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java index 0e49b5f3cd2a..1d042776efc9 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java @@ -83,11 +83,11 @@ public class GlobalActionsGridLayout extends MultiListLayout { } @Override - public ViewGroup getParentView(boolean separated, int index) { + public ViewGroup getParentView(boolean separated, int index, boolean reverseOrder) { if (separated) { return getSeparatedView(); } else { - return getListView().getParentView(index); + return getListView().getParentView(index, reverseOrder); } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java index 37755155751f..d5dcd74c7ea8 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java @@ -28,16 +28,13 @@ import android.widget.LinearLayout; * * * Try to maintain a 'square' grid (equal number of columns and rows) based on the expected item * count. + * * Determine the position and parent of any item by its index and the total item count. * * Display and hide sub-lists as needed, depending on the expected item count. - * * Favor bias toward having more rows or columns depending on the orientation of the device - * (TODO(123344999): Implement this, currently always favors adding more rows.) - * * Change the orientation (horizontal vs. vertical) of the container and sub-lists to act as rows - * or columns depending on the orientation of the device. - * (TODO(123344999): Implement this, currently always columns.) * * While we could implement this behavior with a GridLayout, it would take significantly more * time and effort, and would require more substantial refactoring of the existing code in - * GlobalActionsDialog, since it would require manipulation of the child items themselves. + * GlobalActionsDialog, since it would require manipulation of layout properties on the child items + * themselves. * */ @@ -65,14 +62,25 @@ public class ListGridLayout extends LinearLayout { /** * Get the parent view associated with the item which should be placed at the given position. */ - public ViewGroup getParentView(int index) { - ViewGroup firstParent = (ViewGroup) getChildAt(0); + public ViewGroup getParentView(int index, boolean reverseSublists) { if (mRows == 0) { - return firstParent; + return null; } + int column = getParentViewIndex(index, reverseSublists); + return (ViewGroup) getChildAt(column); + } + + private int reverseSublistIndex(int index) { + return getChildCount() - (index + 1); + } + + private int getParentViewIndex(int index, boolean reverseSublists) { int column = (int) Math.floor(index / mRows); - ViewGroup parent = (ViewGroup) getChildAt(column); - return parent != null ? parent : firstParent; + int columnCount = getChildCount(); + if (reverseSublists) { + column = reverseSublistIndex(column); + } + return column; } /** diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt index f7ca51d6f840..a6e48f8835c7 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt @@ -62,4 +62,6 @@ data class PrivacyApplication(val packageName: String, val uid: Int, val context context.packageManager.getApplicationLabel(it) as String } ?: packageName } + + override fun toString() = "PrivacyApplication(packageName=$packageName, uid=$uid)" } diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt index 0f3393708bcd..625eacd7e2a7 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt @@ -31,6 +31,9 @@ import com.android.systemui.Dependency.MAIN_HANDLER_NAME import com.android.systemui.R import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController +import com.android.systemui.Dumpable +import java.io.FileDescriptor +import java.io.PrintWriter import java.lang.ref.WeakReference import javax.inject.Inject import javax.inject.Named @@ -42,7 +45,7 @@ class PrivacyItemController @Inject constructor( private val appOpsController: AppOpsController, @Named(MAIN_HANDLER_NAME) private val uiHandler: Handler, @Named(BG_HANDLER_NAME) private val bgHandler: Handler -) { +) : Dumpable { companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, @@ -56,7 +59,10 @@ class PrivacyItemController @Inject constructor( const val SYSTEM_UID = 1000 } - private var privacyList = emptyList<PrivacyItem>() + @VisibleForTesting + internal var privacyList = emptyList<PrivacyItem>() + get() = field.toList() // Provides a shallow copy of the list + private val userManager = context.getSystemService(UserManager::class.java) private var currentUserIds = emptyList<Int>() private var listening = false @@ -189,4 +195,22 @@ class PrivacyItemController @Inject constructor( callback?.privacyChanged(list) } } + + override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) { + pw?.println("PrivacyItemController state:") + pw?.println(" Listening: $listening") + pw?.println(" Current user ids: $currentUserIds") + pw?.println(" Privacy Items:") + privacyList.forEach { + pw?.print(" ") + pw?.println(it.toString()) + } + pw?.println(" Callbacks:") + callbacks.forEach { + it.get()?.let { + pw?.print(" ") + pw?.println(it.toString()) + } + } + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 2799191a886f..e0c5e59b73f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -92,6 +92,8 @@ import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.NotificationChannels; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.List; import java.util.Locale; @@ -793,6 +795,15 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, boolean showMicrophone = false; boolean showLocation = false; for (PrivacyItem item : items) { + if (item == null /* b/124234367 */) { + if (DEBUG) { + Log.e(TAG, "updatePrivacyItems - null item found"); + StringWriter out = new StringWriter(); + mPrivacyItemController.dump(null, new PrintWriter(out), null); + Log.e(TAG, out.toString()); + } + continue; + } switch (item.getPrivacyType()) { case TYPE_CAMERA: showCamera = true; diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index d9315f937867..ca72602f2c2b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -82,6 +82,8 @@ public class BubbleControllerTest extends SysuiTestCase { @Mock private BubbleController.BubbleExpandListener mBubbleExpandListener; + private BubbleData mBubbleData; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -104,7 +106,9 @@ public class BubbleControllerTest extends SysuiTestCase { when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel); when(mNotificationData.getChannel(mNoChannelRow.getEntry().key)).thenReturn(null); - mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController); + mBubbleData = new BubbleData(); + mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController, + mBubbleData); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); @@ -112,9 +116,6 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mNotificationEntryManager, atLeastOnce()) .addNotificationEntryListener(mEntryListenerCaptor.capture()); mEntryListener = mEntryListenerCaptor.getValue(); - - // Reset the data - BubbleData.getInstance().clear(); } @Test @@ -300,8 +301,8 @@ public class BubbleControllerTest extends SysuiTestCase { static class TestableBubbleController extends BubbleController { TestableBubbleController(Context context, - StatusBarWindowController statusBarWindowController) { - super(context, statusBarWindowController); + StatusBarWindowController statusBarWindowController, BubbleData data) { + super(context, statusBarWindowController, data); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt index 5d3f6cacc80f..bb384dd52875 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt @@ -35,7 +35,12 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController +import org.hamcrest.Matchers.hasItem +import org.hamcrest.Matchers.not +import org.hamcrest.Matchers.nullValue import org.junit.Assert.assertEquals +import org.junit.Assert.assertThat +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -240,4 +245,26 @@ class PrivacyItemControllerTest : SysuiTestCase() { verify(callback, never()).privacyChanged(anyList()) verify(otherCallback).privacyChanged(anyList()) } + + @Test + fun testListShouldNotHaveNull() { + doReturn(listOf(AppOpItem(AppOpsManager.OP_ACTIVATE_VPN, TEST_UID, "", 0), + AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0))) + .`when`(appOpsController).getActiveAppOpsForUser(anyInt()) + privacyItemController.addCallback(callback) + testableLooper.processAllMessages() + + verify(callback).privacyChanged(capture(argCaptor)) + assertEquals(1, argCaptor.value.size) + assertThat(argCaptor.value, not(hasItem(nullValue()))) + } + + @Test + fun testListShouldBeCopy() { + val list = listOf(PrivacyItem(PrivacyType.TYPE_CAMERA, + PrivacyApplication("", TEST_UID, mContext))) + privacyItemController.privacyList = list + assertEquals(list, privacyItemController.privacyList) + assertTrue(list !== privacyItemController.privacyList) + } }
\ No newline at end of file diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 0b0934bc5a5e..9d92ea2b5b45 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -1645,36 +1645,6 @@ public class LocationManagerService extends ILocationManager.Stub { } } - private abstract static class LinkedListenerBase implements IBinder.DeathRecipient { - protected final CallerIdentity mCallerIdentity; - protected final String mListenerName; - - private LinkedListenerBase(@NonNull CallerIdentity callerIdentity, - @NonNull String listenerName) { - mCallerIdentity = callerIdentity; - mListenerName = listenerName; - } - } - - private static class LinkedListener<TListener> extends LinkedListenerBase { - private final TListener mListener; - private final Consumer<TListener> mBinderDeathCallback; - - private LinkedListener(@NonNull TListener listener, String listenerName, - @NonNull CallerIdentity callerIdentity, - @NonNull Consumer<TListener> binderDeathCallback) { - super(callerIdentity, listenerName); - mListener = listener; - mBinderDeathCallback = binderDeathCallback; - } - - @Override - public void binderDied() { - if (D) Log.d(TAG, "Remote " + mListenerName + " died."); - mBinderDeathCallback.accept(mListener); - } - } - @Override public void removeGnssBatchingCallback() { synchronized (mLock) { @@ -2711,77 +2681,85 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName) { - if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) { - return false; - } + return addGnssDataListener(listener, packageName, "GnssStatusListener", + mGnssStatusProvider, mGnssStatusListeners, + this::unregisterGnssStatusCallback); + } - CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), - Binder.getCallingPid(), packageName); - LinkedListener<IGnssStatusListener> linkedListener = new LinkedListener<>(listener, - "GnssStatusListener", callerIdentity, this::unregisterGnssStatusCallback); - IBinder binder = listener.asBinder(); - synchronized (mLock) { - if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) { - return false; - } + @Override + public void unregisterGnssStatusCallback(IGnssStatusListener listener) { + removeGnssDataListener(listener, mGnssStatusProvider, mGnssStatusListeners); + } - mGnssStatusListeners.put(binder, linkedListener); - long identity = Binder.clearCallingIdentity(); - try { - if (isThrottlingExemptLocked(callerIdentity) - || isImportanceForeground( - mActivityManager.getPackageImportance(packageName))) { - mGnssStatusProvider.addListener(listener, callerIdentity); - } - return true; - } finally { - Binder.restoreCallingIdentity(identity); - } - } + @Override + public boolean addGnssMeasurementsListener( + IGnssMeasurementsListener listener, String packageName) { + return addGnssDataListener(listener, packageName, "GnssMeasurementsListener", + mGnssMeasurementsProvider, mGnssMeasurementsListeners, + this::removeGnssMeasurementsListener); } @Override - public void unregisterGnssStatusCallback(IGnssStatusListener listener) { - if (mGnssStatusProvider == null) { - return; + public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { + removeGnssDataListener(listener, mGnssMeasurementsProvider, mGnssMeasurementsListeners); + } + + private abstract static class LinkedListenerBase implements IBinder.DeathRecipient { + protected final CallerIdentity mCallerIdentity; + protected final String mListenerName; + + private LinkedListenerBase(@NonNull CallerIdentity callerIdentity, + @NonNull String listenerName) { + mCallerIdentity = callerIdentity; + mListenerName = listenerName; } + } - IBinder binder = listener.asBinder(); - synchronized (mLock) { - LinkedListener<IGnssStatusListener> linkedListener = - mGnssStatusListeners.remove(binder); - if (linkedListener == null) { - return; - } - unlinkFromListenerDeathNotificationLocked(binder, linkedListener); - mGnssStatusProvider.removeListener(listener); + private static class LinkedListener<TListener> extends LinkedListenerBase { + private final TListener mListener; + private final Consumer<TListener> mBinderDeathCallback; + + private LinkedListener(@NonNull TListener listener, String listenerName, + @NonNull CallerIdentity callerIdentity, + @NonNull Consumer<TListener> binderDeathCallback) { + super(callerIdentity, listenerName); + mListener = listener; + mBinderDeathCallback = binderDeathCallback; + } + + @Override + public void binderDied() { + if (D) Log.d(TAG, "Remote " + mListenerName + " died."); + mBinderDeathCallback.accept(mListener); } } - @Override - public boolean addGnssMeasurementsListener( - IGnssMeasurementsListener listener, String packageName) { - if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { + private <TListener extends IInterface> boolean addGnssDataListener( + TListener listener, String packageName, String listenerName, + RemoteListenerHelper<TListener> gnssDataProvider, + ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners, + Consumer<TListener> binderDeathCallback) { + if (!hasGnssPermissions(packageName) || gnssDataProvider == null) { return false; } CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName); - LinkedListener<IGnssMeasurementsListener> linkedListener = new LinkedListener<>(listener, - "GnssMeasurementsListener", callerIdentity, this::removeGnssMeasurementsListener); + LinkedListener<TListener> linkedListener = new LinkedListener<>(listener, + listenerName, callerIdentity, binderDeathCallback); IBinder binder = listener.asBinder(); synchronized (mLock) { if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) { return false; } - mGnssMeasurementsListeners.put(binder, linkedListener); + gnssDataListeners.put(binder, linkedListener); long identity = Binder.clearCallingIdentity(); try { if (isThrottlingExemptLocked(callerIdentity) || isImportanceForeground( mActivityManager.getPackageImportance(packageName))) { - mGnssMeasurementsProvider.addListener(listener, callerIdentity); + gnssDataProvider.addListener(listener, callerIdentity); } return true; } finally { @@ -2790,25 +2768,24 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @Override - public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { - if (mGnssMeasurementsProvider == null) { + private <TListener extends IInterface> void removeGnssDataListener( + TListener listener, RemoteListenerHelper<TListener> gnssDataProvider, + ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners) { + if (gnssDataProvider == null) { return; } IBinder binder = listener.asBinder(); synchronized (mLock) { - LinkedListener<IGnssMeasurementsListener> linkedListener = - mGnssMeasurementsListeners.remove(binder); + LinkedListener<TListener> linkedListener = gnssDataListeners.remove(binder); if (linkedListener == null) { return; } unlinkFromListenerDeathNotificationLocked(binder, linkedListener); - mGnssMeasurementsProvider.removeListener(listener); + gnssDataProvider.removeListener(listener); } } - private boolean linkToListenerDeathNotificationLocked(IBinder binder, LinkedListenerBase linkedListener) { try { @@ -2864,52 +2841,15 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean addGnssNavigationMessageListener( IGnssNavigationMessageListener listener, String packageName) { - if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) { - return false; - } - - CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), - Binder.getCallingPid(), packageName); - LinkedListener<IGnssNavigationMessageListener> linkedListener = - new LinkedListener<>(listener, "GnssNavigationMessageListener", callerIdentity, - this::removeGnssNavigationMessageListener); - IBinder binder = listener.asBinder(); - synchronized (mLock) { - if (!linkToListenerDeathNotificationLocked(binder, linkedListener)) { - return false; - } - - mGnssNavigationMessageListeners.put(binder, linkedListener); - long identity = Binder.clearCallingIdentity(); - try { - if (isThrottlingExemptLocked(callerIdentity) - || isImportanceForeground( - mActivityManager.getPackageImportance(packageName))) { - mGnssNavigationMessageProvider.addListener(listener, callerIdentity); - } - return true; - } finally { - Binder.restoreCallingIdentity(identity); - } - } + return addGnssDataListener(listener, packageName, "GnssNavigationMessageListener", + mGnssNavigationMessageProvider, mGnssNavigationMessageListeners, + this::removeGnssNavigationMessageListener); } @Override public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { - if (mGnssNavigationMessageProvider == null) { - return; - } - - IBinder binder = listener.asBinder(); - synchronized (mLock) { - LinkedListener<IGnssNavigationMessageListener> linkedListener = - mGnssNavigationMessageListeners.remove(binder); - if (linkedListener == null) { - return; - } - unlinkFromListenerDeathNotificationLocked(binder, linkedListener); - mGnssNavigationMessageProvider.removeListener(listener); - } + removeGnssDataListener(listener, mGnssNavigationMessageProvider, + mGnssNavigationMessageListeners); } @Override diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 24543b7974df..236797b57556 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -477,6 +477,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { mStats.updateRpmStatsLocked(); } + if ((updateFlags & UPDATE_RAIL) != 0) { + mStats.updateRailStatsLocked(); + } + if (bluetoothInfo != null) { if (bluetoothInfo.isValid()) { mStats.updateBluetoothStateLocked(bluetoothInfo); diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 08900328a200..4d5cb8cb4473 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -59,6 +59,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.PowerProfile; +import com.android.internal.os.RailStats; import com.android.internal.os.RpmStats; import com.android.internal.util.DumpUtils; import com.android.internal.util.ParseUtils; @@ -84,7 +85,8 @@ import java.util.concurrent.Future; */ public final class BatteryStatsService extends IBatteryStats.Stub implements PowerManagerInternal.LowPowerModeListener, - BatteryStatsImpl.PlatformIdleStateCallback { + BatteryStatsImpl.PlatformIdleStateCallback, + BatteryStatsImpl.RailEnergyDataCallback { static final String TAG = "BatteryStatsService"; static final boolean DBG = false; @@ -98,6 +100,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub private native void getLowPowerStats(RpmStats rpmStats); private native int getPlatformLowPowerStats(ByteBuffer outBuffer); private native int getSubsystemLowPowerStats(ByteBuffer outBuffer); + private native void getRailEnergyPowerStats(RailStats railStats); private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8 .newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) @@ -121,6 +124,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub } @Override + public void fillRailDataStats(RailStats railStats) { + if (DBG) Slog.d(TAG, "begin getRailEnergyPowerStats"); + try { + getRailEnergyPowerStats(railStats); + } finally { + if (DBG) Slog.d(TAG, "end getRailEnergyPowerStats"); + } + } + + @Override public String getPlatformLowPowerStats() { if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats"); try { @@ -177,7 +190,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub return (umi != null) ? umi.getUserIds() : null; } }; - mStats = new BatteryStatsImpl(systemDir, handler, this, mUserManagerUserInfoProvider); + mStats = new BatteryStatsImpl(systemDir, handler, this, + this, mUserManagerUserInfoProvider); mWorker = new BatteryExternalStatsWorker(context, mStats); mStats.setExternalStatsSyncLocked(mWorker); mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger( @@ -1460,7 +1474,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub in.unmarshall(raw, 0, raw.length); in.setDataPosition(0); BatteryStatsImpl checkinStats = new BatteryStatsImpl( - null, mStats.mHandler, null, mUserManagerUserInfoProvider); + null, mStats.mHandler, null, null, + mUserManagerUserInfoProvider); checkinStats.readSummaryFromParcel(in); in.recycle(); checkinStats.dumpProtoLocked( @@ -1498,7 +1513,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub in.unmarshall(raw, 0, raw.length); in.setDataPosition(0); BatteryStatsImpl checkinStats = new BatteryStatsImpl( - null, mStats.mHandler, null, mUserManagerUserInfoProvider); + null, mStats.mHandler, null, null, + mUserManagerUserInfoProvider); checkinStats.readSummaryFromParcel(in); in.recycle(); checkinStats.dumpCheckinLocked(mContext, pw, apps, flags, diff --git a/services/core/java/com/android/server/appbinding/AppBindingService.java b/services/core/java/com/android/server/appbinding/AppBindingService.java index 0b6a4329d15b..bbe4ed15b3a0 100644 --- a/services/core/java/com/android/server/appbinding/AppBindingService.java +++ b/services/core/java/com/android/server/appbinding/AppBindingService.java @@ -177,13 +177,12 @@ public class AppBindingService extends Binder { * Handle boot phase PHASE_ACTIVITY_MANAGER_READY. */ private void onPhaseActivityManagerReady() { + // RoleManager doesn't tell us about upgrade, so we still need to listen for app upgrades. + // (app uninstall/disable will be notified by RoleManager.) final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); - packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); - packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); packageFilter.addDataScheme("package"); - packageFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiverAsUser(mPackageUserMonitor, UserHandle.ALL, packageFilter, null, mHandler); @@ -256,14 +255,6 @@ public class AppBindingService extends Binder { handlePackageAddedReplacing(packageName, userId); } break; - case Intent.ACTION_PACKAGE_REMOVED: - if (!replacing) { - handlePackageRemoved(packageName, userId); - } - break; - case Intent.ACTION_PACKAGE_CHANGED: - handlePackageChanged(packageName, userId); - break; } } }; @@ -371,31 +362,6 @@ public class AppBindingService extends Binder { } } - private void handlePackageRemoved(String packageName, int userId) { - if (DEBUG) { - Slog.d(TAG, "handlePackageRemoved: u" + userId + " " + packageName); - } - synchronized (mLock) { - final AppServiceFinder finder = findFinderLocked(userId, packageName); - if (finder != null) { - unbindServicesLocked(userId, finder, "package uninstall"); - } - } - } - - private void handlePackageChanged(String packageName, int userId) { - if (DEBUG) { - Slog.d(TAG, "handlePackageChanged: u" + userId + " " + packageName); - } - synchronized (mLock) { - final AppServiceFinder finder = findFinderLocked(userId, packageName); - if (finder != null) { - unbindServicesLocked(userId, finder, "package changed"); - bindServicesLocked(userId, finder, "package changed"); - } - } - } - private void rebindAllLocked(String reason) { for (int i = 0; i < mRunningUsers.size(); i++) { if (!mRunningUsers.valueAt(i)) { diff --git a/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java b/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java index 4c5f1a1c7b49..753d3b0cc10e 100644 --- a/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java +++ b/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java @@ -16,14 +16,10 @@ package com.android.server.appbinding.finders; -import static android.provider.Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL; - import android.Manifest.permission; -import android.content.BroadcastReceiver; -import android.content.ComponentName; +import android.app.role.OnRoleHoldersChangedListener; +import android.app.role.RoleManager; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.ServiceInfo; import android.os.Handler; import android.os.IBinder; @@ -35,7 +31,8 @@ import android.text.TextUtils; import android.util.Slog; import com.android.internal.R; -import com.android.internal.telephony.SmsApplication; +import com.android.internal.os.BackgroundThread; +import com.android.internal.util.CollectionUtils; import com.android.server.appbinding.AppBindingConstants; import java.util.function.BiConsumer; @@ -45,10 +42,15 @@ import java.util.function.BiConsumer; */ public class CarrierMessagingClientServiceFinder extends AppServiceFinder<CarrierMessagingClientService, ICarrierMessagingClientService> { + + private final RoleManager mRoleManager; + public CarrierMessagingClientServiceFinder(Context context, BiConsumer<AppServiceFinder, Integer> listener, Handler callbackHandler) { super(context, listener, callbackHandler); + + mRoleManager = context.getSystemService(RoleManager.class); } @Override @@ -84,9 +86,8 @@ public class CarrierMessagingClientServiceFinder @Override public String getTargetPackage(int userId) { - final ComponentName cn = SmsApplication.getDefaultSmsApplicationAsUser( - mContext, /* updateIfNeeded= */ true, userId); - String ret = cn == null ? null : cn.getPackageName(); + final String ret = CollectionUtils.firstOrNull(mRoleManager.getRoleHoldersAsUser( + RoleManager.ROLE_SMS, UserHandle.of(userId))); if (DEBUG) { Slog.d(TAG, "getTargetPackage()=" + ret); @@ -97,9 +98,8 @@ public class CarrierMessagingClientServiceFinder @Override public void startMonitoring() { - final IntentFilter filter = new IntentFilter(ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL); - mContext.registerReceiverAsUser(mSmsAppChangedWatcher, UserHandle.ALL, filter, - /* permission= */ null, mHandler); + mRoleManager.addOnRoleHoldersChangedListenerAsUser( + mContext.getMainExecutor(), mRoleHolderChangedListener, UserHandle.ALL); } @Override @@ -118,12 +118,11 @@ public class CarrierMessagingClientServiceFinder return constants.SMS_APP_BIND_FLAGS; } - private final BroadcastReceiver mSmsAppChangedWatcher = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL.equals(intent.getAction())) { - mListener.accept(CarrierMessagingClientServiceFinder.this, getSendingUserId()); - } + private final OnRoleHoldersChangedListener mRoleHolderChangedListener = (role, user) -> { + if (RoleManager.ROLE_SMS.equals(role)) { + BackgroundThread.getHandler().post(() -> { + mListener.accept(CarrierMessagingClientServiceFinder.this, user.getIdentifier()); + }); } }; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 941de895e513..61a1a2f81101 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -985,6 +985,9 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mPackages") private PackageManagerInternal.DefaultBrowserProvider mDefaultBrowserProvider; + @GuardedBy("mPackages") + private PackageManagerInternal.DefaultHomeProvider mDefaultHomeProvider; + private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> { private Context mContext; private ComponentName mIntentFilterVerifierComponent; @@ -1349,7 +1352,7 @@ public class PackageManagerService extends IPackageManager.Stub final @Nullable String mRequiredVerifierPackage; final @NonNull String mRequiredInstallerPackage; final @NonNull String mRequiredUninstallerPackage; - final String mRequiredPermissionControllerPackage; + final @NonNull String mRequiredPermissionControllerPackage; final @Nullable String mSetupWizardPackage; final @Nullable String mStorageManagerPackage; final @Nullable String mSystemTextClassifierPackage; @@ -1940,6 +1943,10 @@ public class PackageManagerService extends IPackageManager.Stub // We may also need to apply pending (restored) runtime // permission grants within these users. mSettings.applyPendingPermissionGrantsLPw(packageName, userId); + + // Persistent preferred activity might have came into effect due to this + // install. + updateDefaultHomeLPw(userId); } } } @@ -19077,6 +19084,7 @@ public class PackageManagerService extends IPackageManager.Stub pir.addFilter(new PreferredActivity(filter, match, set, activity, always)); scheduleWritePackageRestrictionsLocked(userId); postPreferredActivityChangedBroadcast(userId); + updateDefaultHomeLPw(userId); } } @@ -19227,6 +19235,13 @@ public class PackageManagerService extends IPackageManager.Stub /** This method takes a specific user id as well as UserHandle.USER_ALL. */ @GuardedBy("mPackages") boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) { + return clearPackagePreferredActivitiesLPw(packageName, false, userId); + } + + /** This method takes a specific user id as well as UserHandle.USER_ALL. */ + @GuardedBy("mPackages") + private boolean clearPackagePreferredActivitiesLPw(String packageName, + boolean skipUpdateDefaultHome, int userId) { ArrayList<PreferredActivity> removed = null; boolean changed = false; for (int i=0; i<mSettings.mPreferredActivities.size(); i++) { @@ -19255,6 +19270,9 @@ public class PackageManagerService extends IPackageManager.Stub pir.removeFilter(pa); } changed = true; + if (!skipUpdateDefaultHome) { + updateDefaultHomeLPw(thisUserId); + } } } if (changed) { @@ -19314,8 +19332,9 @@ public class PackageManagerService extends IPackageManager.Stub // writer try { synchronized (mPackages) { - clearPackagePreferredActivitiesLPw(null, userId); + clearPackagePreferredActivitiesLPw(null, true, userId); mSettings.applyDefaultPreferredAppsLPw(userId); + updateDefaultHomeLPw(userId); // TODO: We have to reset the default SMS and Phone. This requires // significant refactoring to keep all default apps in the package // manager (cleaner but more work) or have the services provide @@ -19384,6 +19403,7 @@ public class PackageManagerService extends IPackageManager.Stub new PersistentPreferredActivity(filter, activity)); scheduleWritePackageRestrictionsLocked(userId); postPreferredActivityChangedBroadcast(userId); + updateDefaultHomeLPw(userId); } } @@ -19427,6 +19447,7 @@ public class PackageManagerService extends IPackageManager.Stub if (changed) { scheduleWritePackageRestrictionsLocked(userId); postPreferredActivityChangedBroadcast(userId); + updateDefaultHomeLPw(userId); } } } @@ -19514,6 +19535,7 @@ public class PackageManagerService extends IPackageManager.Stub (readParser, readUserId) -> { synchronized (mPackages) { mSettings.readPreferredActivitiesLPw(readParser, readUserId); + updateDefaultHomeLPw(readUserId); } }); } catch (Exception e) { @@ -19569,8 +19591,17 @@ public class PackageManagerService extends IPackageManager.Stub parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name()); restoreFromXml(parser, userId, TAG_DEFAULT_APPS, (parser1, userId1) -> { + String defaultBrowser; synchronized (mPackages) { mSettings.readDefaultAppsLPw(parser1, userId1); + defaultBrowser = mSettings.removeDefaultBrowserPackageNameLPw(userId1); + } + if (defaultBrowser != null) { + PackageManagerInternal.DefaultBrowserProvider provider; + synchronized (mPackages) { + provider = mDefaultBrowserProvider; + } + provider.setDefaultBrowser(defaultBrowser, userId1); } }); } catch (Exception e) { @@ -19928,19 +19959,59 @@ public class PackageManagerService extends IPackageManager.Stub ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, int userId) { Intent intent = getHomeIntent(); - List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null, + List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null, PackageManager.GET_META_DATA, userId); - ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0, - true, false, false, userId); - allHomeCandidates.clear(); - if (list != null) { - allHomeCandidates.addAll(list); + if (resolveInfos == null) { + return null; + } + allHomeCandidates.addAll(resolveInfos); + + PackageManagerInternal.DefaultHomeProvider provider; + synchronized (mPackages) { + provider = mDefaultHomeProvider; + } + if (provider == null) { + Slog.e(TAG, "mDefaultHomeProvider is null"); + return null; } - return (preferred == null || preferred.activityInfo == null) - ? null - : new ComponentName(preferred.activityInfo.packageName, - preferred.activityInfo.name); + String packageName = provider.getDefaultHome(userId); + if (packageName == null) { + return null; + } + int resolveInfosSize = resolveInfos.size(); + for (int i = 0; i < resolveInfosSize; i++) { + ResolveInfo resolveInfo = resolveInfos.get(i); + + if (resolveInfo.activityInfo != null && TextUtils.equals( + resolveInfo.activityInfo.packageName, packageName)) { + return new ComponentName(resolveInfo.activityInfo.packageName, + resolveInfo.activityInfo.name); + } + } + return null; + } + + private void updateDefaultHomeLPw(int userId) { + Intent intent = getHomeIntent(); + List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null, + PackageManager.GET_META_DATA, userId); + ResolveInfo preferredResolveInfo = findPreferredActivity(intent, null, 0, resolveInfos, + 0, true, false, false, userId); + String packageName = preferredResolveInfo != null + && preferredResolveInfo.activityInfo != null + ? preferredResolveInfo.activityInfo.packageName : null; + String currentPackageName = mDefaultHomeProvider.getDefaultHome(userId); + if (TextUtils.equals(currentPackageName, packageName)) { + return; + } + String[] callingPackages = getPackagesForUid(Binder.getCallingUid()); + if (callingPackages != null && ArrayUtils.contains(callingPackages, + mRequiredPermissionControllerPackage)) { + // PermissionController manages default home directly. + return; + } + mDefaultHomeProvider.setDefaultHomeAsync(packageName, userId); } @Override @@ -23830,6 +23901,13 @@ public class PackageManagerService extends IPackageManager.Stub mDefaultBrowserProvider = provider; } } + + @Override + public void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider) { + synchronized (mPackages) { + mDefaultHomeProvider = provider; + } + } } @GuardedBy("mPackages") diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java index 3534cf30e2bf..888dd9992bdf 100644 --- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java +++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java @@ -17,10 +17,13 @@ package com.android.server.policy.role; import android.annotation.NonNull; +import android.annotation.UserIdInt; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import android.content.pm.ResolveInfo; import android.os.Debug; import android.provider.Settings; import android.telecom.TelecomManager; @@ -33,6 +36,7 @@ import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.role.RoleManagerService; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -54,19 +58,44 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder @NonNull private final Context mContext; - public LegacyRoleResolutionPolicy(Context context) { + public LegacyRoleResolutionPolicy(@NonNull Context context) { mContext = context; } + @NonNull @Override - public List<String> getRoleHolders(String roleName, int userId) { + public List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId) { switch (roleName) { + case RoleManager.ROLE_ASSISTANT: { + String legacyAssistant = Settings.Secure.getStringForUser( + mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId); + if (legacyAssistant == null || legacyAssistant.isEmpty()) { + return Collections.emptyList(); + } else { + return Collections.singletonList( + ComponentName.unflattenFromString(legacyAssistant).getPackageName()); + } + } + case RoleManager.ROLE_BROWSER: { + PackageManagerInternal packageManagerInternal = LocalServices.getService( + PackageManagerInternal.class); + String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName( + userId); + return CollectionUtils.singletonOrEmpty(packageName); + } + case RoleManager.ROLE_DIALER: { + String setting = Settings.Secure.getStringForUser( + mContext.getContentResolver(), + Settings.Secure.DIALER_DEFAULT_APPLICATION, userId); + return CollectionUtils.singletonOrEmpty(!TextUtils.isEmpty(setting) + ? setting + : mContext.getSystemService(TelecomManager.class).getSystemDialerPackage()); + } case RoleManager.ROLE_SMS: { // Moved over from SmsApplication#getApplication String result = Settings.Secure.getStringForUser( mContext.getContentResolver(), Settings.Secure.SMS_DEFAULT_APPLICATION, userId); - // TODO: STOPSHIP: Remove the following code once we read the value of // config_defaultSms in RoleControllerService. if (result == null) { @@ -92,34 +121,13 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder SmsApplication.SmsApplicationData app = applicationData; result = app == null ? null : app.mPackageName; } - return CollectionUtils.singletonOrEmpty(result); } - case RoleManager.ROLE_ASSISTANT: { - String legacyAssistant = Settings.Secure.getStringForUser( - mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId); - - if (legacyAssistant == null || legacyAssistant.isEmpty()) { - return Collections.emptyList(); - } else { - return Collections.singletonList( - ComponentName.unflattenFromString(legacyAssistant).getPackageName()); - } - } - case RoleManager.ROLE_DIALER: { - String setting = Settings.Secure.getStringForUser( - mContext.getContentResolver(), - Settings.Secure.DIALER_DEFAULT_APPLICATION, userId); - - return CollectionUtils.singletonOrEmpty(!TextUtils.isEmpty(setting) - ? setting - : mContext.getSystemService(TelecomManager.class).getSystemDialerPackage()); - } - case RoleManager.ROLE_BROWSER: { - PackageManagerInternal packageManagerInternal = LocalServices.getService( - PackageManagerInternal.class); - String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName( - userId); + case RoleManager.ROLE_HOME: { + PackageManager packageManager = mContext.getPackageManager(); + List<ResolveInfo> resolveInfos = new ArrayList<>(); + ComponentName componentName = packageManager.getHomeActivities(resolveInfos); + String packageName = componentName != null ? componentName.getPackageName() : null; return CollectionUtils.singletonOrEmpty(packageName); } default: { diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java index 4186154016e2..8740256af04d 100644 --- a/services/core/java/com/android/server/power/AttentionDetector.java +++ b/services/core/java/com/android/server/power/AttentionDetector.java @@ -123,6 +123,9 @@ public class AttentionDetector { public AttentionDetector(Runnable onUserAttention, Object lock) { mOnUserAttention = onUserAttention; mLock = lock; + + // Device starts with an awake state upon boot. + mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE; } public void systemReady(Context context) { @@ -145,7 +148,7 @@ public class AttentionDetector { if (DEBUG) { Slog.d(TAG, "Do not check for attention yet, wait " + (whenToCheck - now)); } - return nextScreenDimming; + return whenToCheck; } else if (whenToStopExtending < whenToCheck) { if (DEBUG) { Slog.d(TAG, "Let device sleep to avoid false results and improve security " diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index 21bf9de5c8b0..d8531210cad8 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -111,7 +111,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C /** @see #getRoleHolders(String, int) */ public interface RoleHoldersResolver { /** @return a list of packages that hold a given role for a given user */ - List<String> getRoleHolders(String roleName, int userId); + @NonNull + List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId); } /** @@ -154,6 +155,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); packageManagerInternal.setDefaultBrowserProvider(new DefaultBrowserProvider()); + packageManagerInternal.setDefaultHomeProvider(new DefaultHomeProvider()); registerUserRemovedReceiver(); } @@ -741,4 +743,33 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } } + + private class DefaultHomeProvider implements PackageManagerInternal.DefaultHomeProvider { + + @Nullable + @Override + public String getDefaultHome(@UserIdInt int userId) { + return CollectionUtils.firstOrNull(getOrCreateUserState(userId).getRoleHolders( + RoleManager.ROLE_HOME)); + } + + @Override + public void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId) { + IRoleManagerCallback callback = new IRoleManagerCallback.Stub() { + @Override + public void onSuccess() {} + @Override + public void onFailure() { + Slog.e(LOG_TAG, "Failed to set default home: " + packageName); + } + }; + if (packageName != null) { + getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME, + packageName, 0, callback); + } else { + getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0, + callback); + } + } + } } diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index 5c19ad33617c..9cbb58d35b9f 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "BatteryStatsService" //#define LOG_NDEBUG 0 +#include <climits> #include <errno.h> #include <fcntl.h> #include <inttypes.h> @@ -28,6 +29,7 @@ #include <sys/types.h> #include <unistd.h> #include <unordered_map> +#include <utility> #include <android/hardware/power/1.0/IPower.h> #include <android/hardware/power/1.1/IPower.h> @@ -87,6 +89,15 @@ std::function<void(JNIEnv*, jobject)> gGetLowPowerStatsImpl = {}; std::function<jint(JNIEnv*, jobject)> gGetPlatformLowPowerStatsImpl = {}; std::function<jint(JNIEnv*, jobject)> gGetSubsystemLowPowerStatsImpl = {}; +// Cellular/Wifi power monitor rail information +static jmethodID jupdateRailData = NULL; +static jmethodID jsetRailStatsAvailability = NULL; + +std::function<void(JNIEnv*, jobject)> gGetRailEnergyPowerStatsImpl = {}; + +std::unordered_map<uint32_t, std::pair<std::string, std::string>> gPowerStatsHalRailNames = {}; +static bool power_monitor_available = false; + // The caller must be holding gPowerHalMutex. static void deinitPowerStatsLocked() { gPowerStatsHalV1_0 = nullptr; @@ -258,6 +269,7 @@ static bool initializePowerStats() { gPowerStatsHalStateNames.clear(); gPowerStatsHalPlatformIds.clear(); gPowerStatsHalSubsystemIds.clear(); + gPowerStatsHalRailNames.clear(); Return<void> ret; ret = gPowerStatsHalV1_0->getPowerEntityInfo([](auto infos, auto status) { @@ -301,6 +313,27 @@ static bool initializePowerStats() { return false; } + // Get Power monitor rails available + ret = gPowerStatsHalV1_0->getRailInfo([](auto rails, auto status) { + if (status != Status::SUCCESS) { + ALOGW("Rail information is not available"); + power_monitor_available = false; + return; + } + + // Fill out rail names/subsystems into gPowerStatsHalRailNames + for (auto rail : rails) { + gPowerStatsHalRailNames.emplace(rail.index, + std::make_pair(rail.railName, rail.subsysName)); + } + if (!gPowerStatsHalRailNames.empty()) { + power_monitor_available = true; + } + }); + if (!checkResultLocked(ret, __func__)) { + return false; + } + return (!gPowerStatsHalEntityNames.empty()) && (!gPowerStatsHalStateNames.empty()); } @@ -517,6 +550,50 @@ static jint getPowerStatsHalSubsystemData(JNIEnv* env, jobject outBuf) { return total_added; } +static void getPowerStatsHalRailEnergyData(JNIEnv* env, jobject jrailStats) { + using android::hardware::power::stats::V1_0::Status; + using android::hardware::power::stats::V1_0::EnergyData; + + if (!getPowerStatsHalLocked()) { + ALOGE("failed to get power stats"); + return; + } + + if (!power_monitor_available) { + env->CallVoidMethod(jrailStats, jsetRailStatsAvailability, false); + ALOGW("Rail energy data is not available"); + return; + } + + // Get power rail energySinceBoot data + Return<void> ret = gPowerStatsHalV1_0->getEnergyData({}, + [&env, &jrailStats](auto energyData, auto status) { + if (status == Status::NOT_SUPPORTED) { + ALOGW("getEnergyData is not supported"); + return; + } + + for (auto data : energyData) { + if (!(data.timestamp > LLONG_MAX || data.energy > LLONG_MAX)) { + env->CallVoidMethod(jrailStats, + jupdateRailData, + data.index, + env->NewStringUTF( + gPowerStatsHalRailNames.at(data.index).first.c_str()), + env->NewStringUTF( + gPowerStatsHalRailNames.at(data.index).second.c_str()), + data.timestamp, + data.energy); + } else { + ALOGE("Java long overflow seen. Rail index %d not updated", data.index); + } + } + }); + if (!checkResultLocked(ret, __func__)) { + ALOGE("getEnergyData failed"); + } +} + // The caller must be holding powerHalMutex. static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) { sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0(); @@ -761,11 +838,13 @@ static void setUpPowerStatsLocked() { gGetLowPowerStatsImpl = getPowerStatsHalLowPowerData; gGetPlatformLowPowerStatsImpl = getPowerStatsHalPlatformData; gGetSubsystemLowPowerStatsImpl = getPowerStatsHalSubsystemData; + gGetRailEnergyPowerStatsImpl = getPowerStatsHalRailEnergyData; } else if (android::hardware::power::V1_0::IPower::getService() != nullptr) { ALOGI("Using power HAL"); gGetLowPowerStatsImpl = getPowerHalLowPowerData; gGetPlatformLowPowerStatsImpl = getPowerHalPlatformData; gGetSubsystemLowPowerStatsImpl = getPowerHalSubsystemData; + gGetRailEnergyPowerStatsImpl = NULL; } } @@ -835,11 +914,44 @@ static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject return -1; } +static void getRailEnergyPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrailStats) { + if (jrailStats == NULL) { + jniThrowException(env, "java/lang/NullPointerException", + "The railstats jni input jobject jrailStats is null."); + return; + } + if (jupdateRailData == NULL) { + ALOGE("A railstats jni jmethodID is null."); + return; + } + + std::lock_guard<std::mutex> lock(gPowerHalMutex); + + if (!gGetRailEnergyPowerStatsImpl) { + setUpPowerStatsLocked(); + } + + if (gGetRailEnergyPowerStatsImpl) { + gGetRailEnergyPowerStatsImpl(env, jrailStats); + return; + } + + if (jsetRailStatsAvailability == NULL) { + ALOGE("setRailStatsAvailability jni jmethodID is null."); + return; + } + env->CallVoidMethod(jrailStats, jsetRailStatsAvailability, false); + ALOGE("Unable to load Power.Stats.HAL. Setting rail availability to false"); + return; +} + static const JNINativeMethod method_table[] = { { "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup }, { "getLowPowerStats", "(Lcom/android/internal/os/RpmStats;)V", (void*)getLowPowerStats }, { "getPlatformLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getPlatformLowPowerStats }, { "getSubsystemLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getSubsystemLowPowerStats }, + { "getRailEnergyPowerStats", "(Lcom/android/internal/os/RailStats;)V", + (void*)getRailEnergyPowerStats }, }; int register_android_server_BatteryStatsService(JNIEnv *env) @@ -850,8 +962,9 @@ int register_android_server_BatteryStatsService(JNIEnv *env) env->FindClass("com/android/internal/os/RpmStats$PowerStatePlatformSleepState"); jclass clsPowerStateSubsystem = env->FindClass("com/android/internal/os/RpmStats$PowerStateSubsystem"); + jclass clsRailStats = env->FindClass("com/android/internal/os/RailStats"); if (clsRpmStats == NULL || clsPowerStatePlatformSleepState == NULL - || clsPowerStateSubsystem == NULL) { + || clsPowerStateSubsystem == NULL || clsRailStats == NULL) { ALOGE("A rpmstats jni jclass is null."); } else { jgetAndUpdatePlatformState = env->GetMethodID(clsRpmStats, "getAndUpdatePlatformState", @@ -862,6 +975,10 @@ int register_android_server_BatteryStatsService(JNIEnv *env) "(Ljava/lang/String;JI)V"); jputState = env->GetMethodID(clsPowerStateSubsystem, "putState", "(Ljava/lang/String;JI)V"); + jupdateRailData = env->GetMethodID(clsRailStats, "updateRailData", + "(JLjava/lang/String;Ljava/lang/String;JJ)V"); + jsetRailStatsAvailability = env->GetMethodID(clsRailStats, "setRailStatsAvailability", + "(Z)V"); } return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService", diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java index 9f1cbcd7ec27..6a937fabd3ec 100644 --- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java +++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java @@ -98,6 +98,15 @@ public class AttentionDetectorTest extends AndroidTestCase { } @Test + public void testUpdateUserActivity_schedulesTheNextCheck() { + long now = SystemClock.uptimeMillis(); + mNextDimming = now; + mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH); + long nextTimeout = mAttentionDetector.updateUserActivity(mNextDimming + 5000L); + assertThat(nextTimeout).isEqualTo(mNextDimming + 5000L); + } + + @Test public void testOnUserActivity_ignoresAfterMaximumExtension() { long now = SystemClock.uptimeMillis(); mAttentionDetector.onUserActivity(now - 15000L, PowerManager.USER_ACTIVITY_EVENT_TOUCH); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java index a03d28b47057..763ea6293fcc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -40,6 +40,7 @@ import android.util.SparseBooleanArray; import android.view.IRecentsAnimationRunner; import android.view.SurfaceControl; +import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; @@ -112,6 +113,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { } @Test + @FlakyTest(bugId = 117117823) public void testIncludedApps_expectTargetAndVisible() { mWm.setRecentsAnimationController(mController); final AppWindowToken homeAppWindow = createAppWindowToken(mDisplayContent, |