diff --git a/AconfigFlags.bp b/AconfigFlags.bp index c6ce799f0a247298aae22c7a5d1ec7f74f0948e3..1ae9ada4133882caab6c51d029cfab8e932de161 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -81,6 +81,7 @@ aconfig_declarations_group { "android.view.inputmethod.flags-aconfig-java", "android.webkit.flags-aconfig-java", "android.widget.flags-aconfig-java", + "android.xr.flags-aconfig-java", "art_exported_aconfig_flags_lib", "backstage_power_flags_lib", "backup_flags_lib", @@ -109,6 +110,7 @@ aconfig_declarations_group { "hwui_flags_java_lib", "interaction_jank_monitor_flags_lib", "libcore_exported_aconfig_flags_lib", + "libcore_readonly_aconfig_flags_lib", "libgui_flags_java_lib", "power_flags_lib", "sdk_sandbox_flags_lib", @@ -168,6 +170,26 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +// See b/368409430 - This is for libcore flags to be generated with +// force-read-only mode, so access to the flags does not involve I/O, +// which could break Isolated Processes with I/O permission disabled. +// The issue will be addressed once new Aconfig storage API is landed +// and the readonly version will be removed. +aconfig_declarations { + name: "libcore-readonly-aconfig-flags", + package: "com.android.libcore.readonly", + container: "system", + srcs: ["libcore-readonly.aconfig"], +} + +// Core Libraries / libcore +java_aconfig_library { + name: "libcore_readonly_aconfig_flags_lib", + aconfig_declarations: "libcore-readonly-aconfig-flags", + mode: "force-read-only", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // Telecom java_aconfig_library { name: "telecom_flags_core_java_lib", @@ -791,6 +813,12 @@ java_aconfig_library { ], } +cc_aconfig_library { + name: "android.permission.flags-aconfig-cc", + aconfig_declarations: "android.permission.flags-aconfig", + host_supported: true, +} + // SQLite aconfig_declarations { name: "android.database.sqlite-aconfig", @@ -893,6 +921,20 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } +// XR +aconfig_declarations { + name: "android.xr.flags-aconfig", + package: "android.xr", + container: "system", + srcs: ["core/java/android/content/pm/xr.aconfig"], +} + +java_aconfig_library { + name: "android.xr.flags-aconfig-java", + aconfig_declarations: "android.xr.flags-aconfig", + defaults: ["framework-minus-apex-aconfig-java-defaults"], +} + // android.app aconfig_declarations { name: "android.app.flags-aconfig", diff --git a/MULTIUSER_OWNERS b/MULTIUSER_OWNERS index b8857ecd0a935eea0868b462673bb6f9c8387b63..1738a35c6925fb62e90a429147cf2f498b8c53aa 100644 --- a/MULTIUSER_OWNERS +++ b/MULTIUSER_OWNERS @@ -3,7 +3,5 @@ annabauza@google.com bookatz@google.com nykkumar@google.com olilan@google.com -omakoto@google.com tetianameronyk@google.com tyk@google.com -yamasani@google.com diff --git a/OWNERS b/OWNERS index afa60bea5aa0b716a92e653f47c44191ed314e97..eb2bfcfdf82da9d8635338e1ab54f7503ca6fc6b 100644 --- a/OWNERS +++ b/OWNERS @@ -7,8 +7,6 @@ dsandler@google.com #{LAST_RESORT_SUGGESTION} hackbod@android.com #{LAST_RESORT_SUGGESTION} hackbod@google.com #{LAST_RESORT_SUGGESTION} jjaggi@google.com #{LAST_RESORT_SUGGESTION} -jsharkey@android.com #{LAST_RESORT_SUGGESTION} -jsharkey@google.com #{LAST_RESORT_SUGGESTION} lorenzo@google.com #{LAST_RESORT_SUGGESTION} michaelwr@google.com #{LAST_RESORT_SUGGESTION} nandana@google.com #{LAST_RESORT_SUGGESTION} @@ -33,19 +31,19 @@ per-file **.bp,**.mk =joeo@google.com, lamontjones@google.com per-file TestProtoLibraries.bp = file:platform/platform_testing:/libraries/health/OWNERS per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS -per-file INPUT_OWNERS = file:/INPUT_OWNERS -per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS -per-file SQLITE_OWNERS = file:/SQLITE_OWNERS - per-file *ravenwood* = file:ravenwood/OWNERS per-file *Ravenwood* = file:ravenwood/OWNERS +per-file INPUT_OWNERS = file:/INPUT_OWNERS +per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS +per-file SQLITE_OWNERS = file:/SQLITE_OWNERS per-file PERFORMANCE_OWNERS = file:/PERFORMANCE_OWNERS - per-file PACKAGE_MANAGER_OWNERS = file:/PACKAGE_MANAGER_OWNERS - per-file WEAR_OWNERS = file:/WEAR_OWNERS - +per-file ACTIVITY_MANAGER_OWNERS = file:/ACTIVITY_MANAGER_OWNERS +per-file BATTERY_STATS_OWNERS = file:/BATTERY_STATS_OWNERS +per-file OOM_ADJUSTER_OWNERS = file:/OOM_ADJUSTER_OWNERS +per-file MULTIUSER_OWNERS = file:/MULTIUSER_OWNERS +per-file BROADCASTS_OWNERS = file:/BROADCASTS_OWNERS per-file ADPF_OWNERS = file:/ADPF_OWNERS - per-file GAME_MANAGER_OWNERS = file:/GAME_MANAGER_OWNERS diff --git a/apct-tests/perftests/core/src/android/os/MessageQueuePerfTest.java b/apct-tests/perftests/core/src/android/os/MessageQueuePerfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b14de836fa7810891dd6c8ffbd1cdb09f78ab8aa --- /dev/null +++ b/apct-tests/perftests/core/src/android/os/MessageQueuePerfTest.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.app.Activity; +import android.app.Instrumentation; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; +import android.perftests.utils.Stats; +import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.LargeTest; +import androidx.test.runner.AndroidJUnit4; + +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.Random; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Performance tests for {@link MessageQueue}. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class MessageQueuePerfTest { + static final String TAG = "MessageQueuePerfTest"; + private static final int PER_THREAD_MESSAGE_COUNT = 1000; + private static final int THREAD_COUNT = 8; + private static final int TOTAL_MESSAGE_COUNT = PER_THREAD_MESSAGE_COUNT * THREAD_COUNT; + + static Object sLock = new Object(); + private ArrayList mResults; + + @Before + public void setUp() { } + + @After + public void tearDown() { } + + class EnqueueThread extends Thread { + CountDownLatch mStartLatch; + CountDownLatch mEndLatch; + Handler mHandler; + int mMessageStartIdx; + Message[] mMessages; + long[] mDelays; + + EnqueueThread(CountDownLatch startLatch, CountDownLatch endLatch, Handler handler, + int startIdx, Message[] messages, long[] delays) { + super(); + mStartLatch = startLatch; + mEndLatch = endLatch; + mHandler = handler; + mMessageStartIdx = startIdx; + mMessages = messages; + mDelays = delays; + } + + @Override + public void run() { + Log.d(TAG, "Enqueue thread started at message index " + mMessageStartIdx); + try { + mStartLatch.await(); + } catch (InterruptedException e) { + + } + long now = SystemClock.uptimeMillis(); + long startTimeNS = SystemClock.elapsedRealtimeNanos(); + for (int i = mMessageStartIdx; i < (mMessageStartIdx + PER_THREAD_MESSAGE_COUNT); i++) { + if (mDelays[i] == 0) { + mHandler.sendMessageAtFrontOfQueue(mMessages[i]); + } else { + mHandler.sendMessageAtTime(mMessages[i], now + mDelays[i]); + } + } + long endTimeNS = SystemClock.elapsedRealtimeNanos(); + + synchronized (sLock) { + mResults.add(endTimeNS - startTimeNS); + } + mEndLatch.countDown(); + } + } + + class TestHandler extends Handler { + TestHandler(Looper looper) { + super(looper); + } + + public void handleMessage(Message msg) { } + } + + void reportPerf(String prefix, int threadCount, int perThreadMessageCount) { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + Stats stats = new Stats(mResults); + + Log.d(TAG, "Reporting perf now"); + + Bundle status = new Bundle(); + status.putLong(prefix + "_median_ns", stats.getMedian()); + status.putLong(prefix + "_mean_ns", (long) stats.getMean()); + status.putLong(prefix + "_min_ns", stats.getMin()); + status.putLong(prefix + "_max_ns", stats.getMax()); + status.putLong(prefix + "_stddev_ns", (long) stats.getStandardDeviation()); + status.putLong(prefix + "_nr_threads", threadCount); + status.putLong(prefix + "_msgs_per_thread", perThreadMessageCount); + instrumentation.sendStatus(Activity.RESULT_OK, status); + } + + HandlerThread mHandlerThread; + + private void fillMessagesArray(Message[] messages) { + for (int i = 0; i < messages.length; i++) { + messages[i] = mHandlerThread.getThreadHandler().obtainMessage(i); + } + } + + private void startTestAndWaitOnThreads(CountDownLatch threadStartLatch, CountDownLatch threadEndLatch) { + try { + threadStartLatch.countDown(); + Log.e(TAG, "Test threads started"); + threadEndLatch.await(); + } catch (InterruptedException ignored) { + } + Log.e(TAG, "Test threads ended, quitting handler thread"); + } + + @Test + public void benchmarkEnqueueAtFrontOfQueue() { + CountDownLatch threadStartLatch = new CountDownLatch(1); + CountDownLatch threadEndLatch = new CountDownLatch(THREAD_COUNT); + mHandlerThread = new HandlerThread("MessageQueuePerfTest"); + mHandlerThread.start(); + Message[] messages = new Message[TOTAL_MESSAGE_COUNT]; + fillMessagesArray(messages); + + long[] delays = new long[TOTAL_MESSAGE_COUNT]; + mResults = new ArrayList<>(); + + TestHandler handler = new TestHandler(mHandlerThread.getLooper()); + for (int i = 0; i < THREAD_COUNT; i++) { + EnqueueThread thread = new EnqueueThread(threadStartLatch, threadEndLatch, handler, + i * PER_THREAD_MESSAGE_COUNT, messages, delays); + thread.start(); + } + + startTestAndWaitOnThreads(threadStartLatch, threadEndLatch); + + mHandlerThread.quitSafely(); + + reportPerf("enqueueAtFront", THREAD_COUNT, PER_THREAD_MESSAGE_COUNT); + } + + /** + * Fill array with random delays, for benchmarkEnqueueDelayed + */ + public long[] fillDelayArray() { + long[] delays = new long[TOTAL_MESSAGE_COUNT]; + Random rand = new Random(0xDEADBEEF); + for (int i = 0; i < TOTAL_MESSAGE_COUNT; i++) { + delays[i] = Math.abs(rand.nextLong() % 5000); + } + return delays; + } + + @Test + public void benchmarkEnqueueDelayed() { + CountDownLatch threadStartLatch = new CountDownLatch(1); + CountDownLatch threadEndLatch = new CountDownLatch(THREAD_COUNT); + mHandlerThread = new HandlerThread("MessageQueuePerfTest"); + mHandlerThread.start(); + Message[] messages = new Message[TOTAL_MESSAGE_COUNT]; + fillMessagesArray(messages); + + long[] delays = fillDelayArray(); + mResults = new ArrayList<>(); + + TestHandler handler = new TestHandler(mHandlerThread.getLooper()); + for (int i = 0; i < THREAD_COUNT; i++) { + EnqueueThread thread = new EnqueueThread(threadStartLatch, threadEndLatch, handler, + i * PER_THREAD_MESSAGE_COUNT, messages, delays); + thread.start(); + } + + startTestAndWaitOnThreads(threadStartLatch, threadEndLatch); + + mHandlerThread.quitSafely(); + + reportPerf("enqueueDelayed", THREAD_COUNT, PER_THREAD_MESSAGE_COUNT); + } +} diff --git a/apex/jobscheduler/service/aconfig/app_idle.aconfig b/apex/jobscheduler/service/aconfig/app_idle.aconfig index c8976ca8361e51ccc72d50caeae50ea5d8fb9965..f079c02707e07d81b325453480119d1ccede5f10 100644 --- a/apex/jobscheduler/service/aconfig/app_idle.aconfig +++ b/apex/jobscheduler/service/aconfig/app_idle.aconfig @@ -12,3 +12,12 @@ flag { } } +flag { + name: "screen_time_bypass" + namespace: "backstage_power" + description: "Bypass the screen time check for bucket evaluation" + bug: "374114769" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/apex/jobscheduler/service/aconfig/job.aconfig b/apex/jobscheduler/service/aconfig/job.aconfig index 11c5b51e23ae564e6b154b064fcea813ce7610e1..98e53ab978728a60cadf4ec1acb71abfb5c03269 100644 --- a/apex/jobscheduler/service/aconfig/job.aconfig +++ b/apex/jobscheduler/service/aconfig/job.aconfig @@ -82,3 +82,10 @@ flag { description: "Applies the normal quota policy to FGS jobs" bug: "341201311" } + +flag { + name: "adjust_quota_default_constants" + namespace: "backstage_power" + description: "Adjust quota default parameters" + bug: "347058927" +} \ No newline at end of file diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index c1894f0f795f62ec77ef2711bd54a98a0548acf1..a37779e681fb18513afbae8bebd026f521d121f4 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -3568,7 +3568,7 @@ public class DeviceIdleController extends SystemService Slog.i(TAG, "becomeActiveLocked, reason=" + activeReason + ", changeLightIdle=" + changeLightIdle); } - if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) { + if (mState != STATE_ACTIVE || mLightState != LIGHT_STATE_ACTIVE) { moveToStateLocked(STATE_ACTIVE, activeReason); mInactiveTimeout = newInactiveTimeout; resetIdleManagementLocked(); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java index 03a3a0d51891154a41c15e3d473f923d81ea28dc..885bad5e31c8aed0bf49fbd7c88ea0b271d97263 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java @@ -394,13 +394,13 @@ public final class QuotaController extends StateController { * minutes to run its jobs. */ private final long[] mBucketPeriodsMs = new long[]{ - QcConstants.DEFAULT_WINDOW_SIZE_ACTIVE_MS, - QcConstants.DEFAULT_WINDOW_SIZE_WORKING_MS, - QcConstants.DEFAULT_WINDOW_SIZE_FREQUENT_MS, + QcConstants.DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS, + QcConstants.DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS, + QcConstants.DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS, QcConstants.DEFAULT_WINDOW_SIZE_RARE_MS, 0, // NEVER QcConstants.DEFAULT_WINDOW_SIZE_RESTRICTED_MS, - QcConstants.DEFAULT_WINDOW_SIZE_EXEMPTED_MS + QcConstants.DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS }; /** The maximum period any bucket can have. */ @@ -454,7 +454,7 @@ public final class QuotaController extends StateController { */ private final long[] mEJLimitsMs = new long[]{ QcConstants.DEFAULT_EJ_LIMIT_ACTIVE_MS, - QcConstants.DEFAULT_EJ_LIMIT_WORKING_MS, + QcConstants.DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS, QcConstants.DEFAULT_EJ_LIMIT_FREQUENT_MS, QcConstants.DEFAULT_EJ_LIMIT_RARE_MS, 0, // NEVER @@ -476,7 +476,8 @@ public final class QuotaController extends StateController { /** * Length of time used to split an app's top time into chunks. */ - private long mEJTopAppTimeChunkSizeMs = QcConstants.DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; + private long mEJTopAppTimeChunkSizeMs = + QcConstants.DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; /** * How much EJ quota to give back to an app based on the number of top app time chunks it had. @@ -486,7 +487,7 @@ public final class QuotaController extends StateController { /** * How much EJ quota to give back to an app based on each non-top user interaction. */ - private long mEJRewardInteractionMs = QcConstants.DEFAULT_EJ_REWARD_INTERACTION_MS; + private long mEJRewardInteractionMs = QcConstants.DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS; /** * How much EJ quota to give back to an app based on each notification seen event. @@ -498,14 +499,6 @@ public final class QuotaController extends StateController { private long mEJGracePeriodTopAppMs = QcConstants.DEFAULT_EJ_GRACE_PERIOD_TOP_APP_MS; - private long mQuotaBumpAdditionalDurationMs = - QcConstants.DEFAULT_QUOTA_BUMP_ADDITIONAL_DURATION_MS; - private int mQuotaBumpAdditionalJobCount = QcConstants.DEFAULT_QUOTA_BUMP_ADDITIONAL_JOB_COUNT; - private int mQuotaBumpAdditionalSessionCount = - QcConstants.DEFAULT_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT; - private long mQuotaBumpWindowSizeMs = QcConstants.DEFAULT_QUOTA_BUMP_WINDOW_SIZE_MS; - private int mQuotaBumpLimit = QcConstants.DEFAULT_QUOTA_BUMP_LIMIT; - /** * List of system apps with the {@link android.Manifest.permission#INSTALL_PACKAGES} permission * granted for each user. @@ -578,6 +571,8 @@ public final class QuotaController extends StateController { } catch (RemoteException e) { // ignored; both services live in system_server } + + processQuotaConstantsAdjustment(); } @Override @@ -1095,7 +1090,7 @@ public final class QuotaController extends StateController { // essentially run until they reach the maximum limit. if (stats.windowSizeMs == mAllowedTimePerPeriodMs[standbyBucket]) { return calculateTimeUntilQuotaConsumedLocked( - events, startMaxElapsed, maxExecutionTimeRemainingMs, false); + events, startMaxElapsed, maxExecutionTimeRemainingMs); } // Need to check both max time and period time in case one is less than the other. @@ -1104,9 +1099,9 @@ public final class QuotaController extends StateController { // bucket value. return Math.min( calculateTimeUntilQuotaConsumedLocked( - events, startMaxElapsed, maxExecutionTimeRemainingMs, false), + events, startMaxElapsed, maxExecutionTimeRemainingMs), calculateTimeUntilQuotaConsumedLocked( - events, startWindowElapsed, allowedTimeRemainingMs, true)); + events, startWindowElapsed, allowedTimeRemainingMs)); } /** @@ -1116,36 +1111,12 @@ public final class QuotaController extends StateController { * @param deadSpaceMs How much time can be allowed to count towards the quota */ private long calculateTimeUntilQuotaConsumedLocked(@NonNull List sessions, - final long windowStartElapsed, long deadSpaceMs, boolean allowQuotaBumps) { + final long windowStartElapsed, long deadSpaceMs) { long timeUntilQuotaConsumedMs = 0; long start = windowStartElapsed; - int numQuotaBumps = 0; - final long quotaBumpWindowStartElapsed = - sElapsedRealtimeClock.millis() - mQuotaBumpWindowSizeMs; final int numSessions = sessions.size(); - if (allowQuotaBumps) { - for (int i = numSessions - 1; i >= 0; --i) { - TimedEvent event = sessions.get(i); - - if (event instanceof QuotaBump) { - if (event.getEndTimeElapsed() >= quotaBumpWindowStartElapsed - && numQuotaBumps++ < mQuotaBumpLimit) { - deadSpaceMs += mQuotaBumpAdditionalDurationMs; - } else { - break; - } - } - } - } for (int i = 0; i < numSessions; ++i) { - TimedEvent event = sessions.get(i); - - if (event instanceof QuotaBump) { - continue; - } - - TimingSession session = (TimingSession) event; - + TimingSession session = (TimingSession) sessions.get(i); if (session.endTimeElapsed < windowStartElapsed) { // Outside of window. Ignore. continue; @@ -1330,41 +1301,15 @@ public final class QuotaController extends StateController { final long startWindowElapsed = nowElapsed - stats.windowSizeMs; final long startMaxElapsed = nowElapsed - MAX_PERIOD_MS; int sessionCountInWindow = 0; - int numQuotaBumps = 0; - final long quotaBumpWindowStartElapsed = nowElapsed - mQuotaBumpWindowSizeMs; // The minimum time between the start time and the beginning of the events that were // looked at --> how much time the stats will be valid for. long emptyTimeMs = Long.MAX_VALUE; // Sessions are non-overlapping and in order of occurrence, so iterating backwards will get // the most recent ones. final int loopStart = events.size() - 1; - // Process QuotaBumps first to ensure the limits are properly adjusted. - for (int i = loopStart; i >= 0; --i) { - TimedEvent event = events.get(i); - - if (event.getEndTimeElapsed() < quotaBumpWindowStartElapsed - || numQuotaBumps >= mQuotaBumpLimit) { - break; - } - - if (event instanceof QuotaBump) { - stats.allowedTimePerPeriodMs += mQuotaBumpAdditionalDurationMs; - stats.jobCountLimit += mQuotaBumpAdditionalJobCount; - stats.sessionCountLimit += mQuotaBumpAdditionalSessionCount; - emptyTimeMs = Math.min(emptyTimeMs, - event.getEndTimeElapsed() - quotaBumpWindowStartElapsed); - numQuotaBumps++; - } - } TimingSession lastSeenTimingSession = null; for (int i = loopStart; i >= 0; --i) { - TimedEvent event = events.get(i); - - if (event instanceof QuotaBump) { - continue; - } - - TimingSession session = (TimingSession) event; + TimingSession session = (TimingSession) events.get(i); // Window management. if (startWindowElapsed < session.endTimeElapsed) { @@ -1469,6 +1414,13 @@ public final class QuotaController extends StateController { } } + void processQuotaConstantsAdjustment() { + if (Flags.adjustQuotaDefaultConstants()) { + mQcConstants.adjustDefaultBucketWindowSizes(); + mQcConstants.adjustDefaultEjLimits(); + } + } + @VisibleForTesting void incrementJobCountLocked(final int userId, @NonNull final String packageName, int count) { final long now = sElapsedRealtimeClock.millis(); @@ -2057,28 +2009,6 @@ public final class QuotaController extends StateController { } } - @VisibleForTesting - static final class QuotaBump implements TimedEvent { - // Event timestamp in elapsed realtime timebase. - public final long eventTimeElapsed; - - QuotaBump(long eventElapsed) { - this.eventTimeElapsed = eventElapsed; - } - - @Override - public long getEndTimeElapsed() { - return eventTimeElapsed; - } - - @Override - public void dump(IndentingPrintWriter pw) { - pw.print("Quota bump @ "); - pw.print(eventTimeElapsed); - pw.println(); - } - } - @VisibleForTesting static final class ShrinkableDebits { /** The amount of quota remaining. Can be negative if limit changes. */ @@ -2528,21 +2458,6 @@ public final class QuotaController extends StateController { updateStandbyBucket(userId, packageName, bucketIndex); }); } - - @Override - public void triggerTemporaryQuotaBump(String packageName, @UserIdInt int userId) { - synchronized (mLock) { - List events = mTimingEvents.get(userId, packageName); - if (events == null || events.size() == 0) { - // If the app hasn't run any jobs, there's no point giving it a quota bump. - return; - } - events.add(new QuotaBump(sElapsedRealtimeClock.millis())); - invalidateAllExecutionStatsLocked(userId, packageName); - } - // Update jobs out of band. - mHandler.obtainMessage(MSG_CHECK_PACKAGE, userId, 0, packageName).sendToTarget(); - } } @VisibleForTesting @@ -3019,7 +2934,6 @@ public final class QuotaController extends StateController { mQcConstants.mRateLimitingConstantsUpdated = false; mQcConstants.mExecutionPeriodConstantsUpdated = false; mQcConstants.mEJLimitConstantsUpdated = false; - mQcConstants.mQuotaBumpConstantsUpdated = false; } @Override @@ -3046,7 +2960,6 @@ public final class QuotaController extends StateController { private boolean mRateLimitingConstantsUpdated = false; private boolean mExecutionPeriodConstantsUpdated = false; private boolean mEJLimitConstantsUpdated = false; - private boolean mQuotaBumpConstantsUpdated = false; /** Prefix to use with all constant keys in order to "sub-namespace" the keys. */ private static final String QC_CONSTANT_PREFIX = "qc_"; @@ -3194,21 +3107,6 @@ public final class QuotaController extends StateController { @VisibleForTesting static final String KEY_EJ_GRACE_PERIOD_TOP_APP_MS = QC_CONSTANT_PREFIX + "ej_grace_period_top_app_ms"; - @VisibleForTesting - static final String KEY_QUOTA_BUMP_ADDITIONAL_DURATION_MS = - QC_CONSTANT_PREFIX + "quota_bump_additional_duration_ms"; - @VisibleForTesting - static final String KEY_QUOTA_BUMP_ADDITIONAL_JOB_COUNT = - QC_CONSTANT_PREFIX + "quota_bump_additional_job_count"; - @VisibleForTesting - static final String KEY_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT = - QC_CONSTANT_PREFIX + "quota_bump_additional_session_count"; - @VisibleForTesting - static final String KEY_QUOTA_BUMP_WINDOW_SIZE_MS = - QC_CONSTANT_PREFIX + "quota_bump_window_size_ms"; - @VisibleForTesting - static final String KEY_QUOTA_BUMP_LIMIT = - QC_CONSTANT_PREFIX + "quota_bump_limit"; private static final long DEFAULT_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS = 10 * 60 * 1000L; // 10 minutes @@ -3224,14 +3122,28 @@ public final class QuotaController extends StateController { 10 * 60 * 1000L; // 10 minutes private static final long DEFAULT_IN_QUOTA_BUFFER_MS = 30 * 1000L; // 30 seconds - private static final long DEFAULT_WINDOW_SIZE_EXEMPTED_MS = + // Legacy default window size for EXEMPTED bucket + private static final long DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS; // EXEMPT apps can run jobs at any time - private static final long DEFAULT_WINDOW_SIZE_ACTIVE_MS = + // Legacy default window size for ACTIVE bucket + private static final long DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_ACTIVE_MS; // ACTIVE apps can run jobs at any time - private static final long DEFAULT_WINDOW_SIZE_WORKING_MS = + // Legacy default window size for WORKING bucket + private static final long DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS = 2 * 60 * 60 * 1000L; // 2 hours - private static final long DEFAULT_WINDOW_SIZE_FREQUENT_MS = + // Legacy default window size for FREQUENT bucket + private static final long DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS = 8 * 60 * 60 * 1000L; // 8 hours + + private static final long DEFAULT_CURRENT_WINDOW_SIZE_EXEMPTED_MS = + 20 * 60 * 1000L; // 20 minutes. + private static final long DEFAULT_CURRENT_WINDOW_SIZE_ACTIVE_MS = + 30 * 60 * 1000L; // 30 minutes. + private static final long DEFAULT_CURRENT_WINDOW_SIZE_WORKING_MS = + 4 * 60 * 60 * 1000L; // 4 hours + private static final long DEFAULT_CURRENT_WINDOW_SIZE_FREQUENT_MS = + 12 * 60 * 60 * 1000L; // 12 hours + private static final long DEFAULT_WINDOW_SIZE_RARE_MS = 24 * 60 * 60 * 1000L; // 24 hours private static final long DEFAULT_WINDOW_SIZE_RESTRICTED_MS = @@ -3245,9 +3157,9 @@ public final class QuotaController extends StateController { 75; // 75/window = 450/hr = 1/session private static final int DEFAULT_MAX_JOB_COUNT_ACTIVE = DEFAULT_MAX_JOB_COUNT_EXEMPTED; private static final int DEFAULT_MAX_JOB_COUNT_WORKING = // 120/window = 60/hr = 12/session - (int) (60.0 * DEFAULT_WINDOW_SIZE_WORKING_MS / HOUR_IN_MILLIS); + (int) (60.0 * DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS / HOUR_IN_MILLIS); private static final int DEFAULT_MAX_JOB_COUNT_FREQUENT = // 200/window = 25/hr = 25/session - (int) (25.0 * DEFAULT_WINDOW_SIZE_FREQUENT_MS / HOUR_IN_MILLIS); + (int) (25.0 * DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS / HOUR_IN_MILLIS); private static final int DEFAULT_MAX_JOB_COUNT_RARE = // 48/window = 2/hr = 16/session (int) (2.0 * DEFAULT_WINDOW_SIZE_RARE_MS / HOUR_IN_MILLIS); private static final int DEFAULT_MAX_JOB_COUNT_RESTRICTED = 10; @@ -3268,24 +3180,24 @@ public final class QuotaController extends StateController { // TODO(267949143): set a different limit for headless system apps private static final long DEFAULT_EJ_LIMIT_EXEMPTED_MS = 60 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_LIMIT_ACTIVE_MS = 30 * MINUTE_IN_MILLIS; - private static final long DEFAULT_EJ_LIMIT_WORKING_MS = DEFAULT_EJ_LIMIT_ACTIVE_MS; + private static final long DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS = DEFAULT_EJ_LIMIT_ACTIVE_MS; + private static final long DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS = 15 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_LIMIT_FREQUENT_MS = 10 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_LIMIT_RARE_MS = DEFAULT_EJ_LIMIT_FREQUENT_MS; private static final long DEFAULT_EJ_LIMIT_RESTRICTED_MS = 5 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_LIMIT_ADDITION_SPECIAL_MS = 15 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_LIMIT_ADDITION_INSTALLER_MS = 30 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_WINDOW_SIZE_MS = 24 * HOUR_IN_MILLIS; - private static final long DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS = 30 * SECOND_IN_MILLIS; + private static final long DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS = + 30 * SECOND_IN_MILLIS; + private static final long DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS = + 5 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_REWARD_TOP_APP_MS = 10 * SECOND_IN_MILLIS; - private static final long DEFAULT_EJ_REWARD_INTERACTION_MS = 15 * SECOND_IN_MILLIS; + private static final long DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS = 15 * SECOND_IN_MILLIS; + private static final long DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS = 5 * SECOND_IN_MILLIS; private static final long DEFAULT_EJ_REWARD_NOTIFICATION_SEEN_MS = 0; private static final long DEFAULT_EJ_GRACE_PERIOD_TEMP_ALLOWLIST_MS = 3 * MINUTE_IN_MILLIS; private static final long DEFAULT_EJ_GRACE_PERIOD_TOP_APP_MS = 1 * MINUTE_IN_MILLIS; - private static final long DEFAULT_QUOTA_BUMP_ADDITIONAL_DURATION_MS = 1 * MINUTE_IN_MILLIS; - private static final int DEFAULT_QUOTA_BUMP_ADDITIONAL_JOB_COUNT = 2; - private static final int DEFAULT_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT = 1; - private static final long DEFAULT_QUOTA_BUMP_WINDOW_SIZE_MS = 8 * HOUR_IN_MILLIS; - private static final int DEFAULT_QUOTA_BUMP_LIMIT = 8; /** * How much time each app in the exempted bucket will have to run jobs within their standby @@ -3332,28 +3244,28 @@ public final class QuotaController extends StateController { * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_EXEMPTED_MS} within the past * WINDOW_SIZE_MS. */ - public long WINDOW_SIZE_EXEMPTED_MS = DEFAULT_WINDOW_SIZE_EXEMPTED_MS; + public long WINDOW_SIZE_EXEMPTED_MS = DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS; /** * The quota window size of the particular standby bucket. Apps in this standby bucket are * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_ACTIVE_MS} within the past * WINDOW_SIZE_MS. */ - public long WINDOW_SIZE_ACTIVE_MS = DEFAULT_WINDOW_SIZE_ACTIVE_MS; + public long WINDOW_SIZE_ACTIVE_MS = DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS; /** * The quota window size of the particular standby bucket. Apps in this standby bucket are * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_WORKING_MS} within the past * WINDOW_SIZE_MS. */ - public long WINDOW_SIZE_WORKING_MS = DEFAULT_WINDOW_SIZE_WORKING_MS; + public long WINDOW_SIZE_WORKING_MS = DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS; /** * The quota window size of the particular standby bucket. Apps in this standby bucket are * expected to run only {@link #ALLOWED_TIME_PER_PERIOD_FREQUENT_MS} within the past * WINDOW_SIZE_MS. */ - public long WINDOW_SIZE_FREQUENT_MS = DEFAULT_WINDOW_SIZE_FREQUENT_MS; + public long WINDOW_SIZE_FREQUENT_MS = DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS; /** * The quota window size of the particular standby bucket. Apps in this standby bucket are @@ -3514,7 +3426,7 @@ public final class QuotaController extends StateController { * standby bucket can only have expedited job sessions totalling EJ_LIMIT (without factoring * in any rewards or free EJs). */ - public long EJ_LIMIT_WORKING_MS = DEFAULT_EJ_LIMIT_WORKING_MS; + public long EJ_LIMIT_WORKING_MS = DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS; /** * The total expedited job session limit of the particular standby bucket. Apps in this @@ -3558,7 +3470,7 @@ public final class QuotaController extends StateController { /** * Length of time used to split an app's top time into chunks. */ - public long EJ_TOP_APP_TIME_CHUNK_SIZE_MS = DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; + public long EJ_TOP_APP_TIME_CHUNK_SIZE_MS = DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; /** * How much EJ quota to give back to an app based on the number of top app time chunks it @@ -3569,7 +3481,7 @@ public final class QuotaController extends StateController { /** * How much EJ quota to give back to an app based on each non-top user interaction. */ - public long EJ_REWARD_INTERACTION_MS = DEFAULT_EJ_REWARD_INTERACTION_MS; + public long EJ_REWARD_INTERACTION_MS = DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS; /** * How much EJ quota to give back to an app based on each notification seen event. @@ -3587,32 +3499,51 @@ public final class QuotaController extends StateController { */ public long EJ_GRACE_PERIOD_TOP_APP_MS = DEFAULT_EJ_GRACE_PERIOD_TOP_APP_MS; - /** - * How much additional session duration to give an app for each accepted quota bump. - */ - public long QUOTA_BUMP_ADDITIONAL_DURATION_MS = DEFAULT_QUOTA_BUMP_ADDITIONAL_DURATION_MS; + void adjustDefaultBucketWindowSizes() { + WINDOW_SIZE_EXEMPTED_MS = DEFAULT_CURRENT_WINDOW_SIZE_EXEMPTED_MS; + WINDOW_SIZE_ACTIVE_MS = DEFAULT_CURRENT_WINDOW_SIZE_ACTIVE_MS; + WINDOW_SIZE_WORKING_MS = DEFAULT_CURRENT_WINDOW_SIZE_WORKING_MS; + WINDOW_SIZE_FREQUENT_MS = DEFAULT_CURRENT_WINDOW_SIZE_FREQUENT_MS; - /** - * How many additional regular jobs to give an app for each accepted quota bump. - */ - public int QUOTA_BUMP_ADDITIONAL_JOB_COUNT = DEFAULT_QUOTA_BUMP_ADDITIONAL_JOB_COUNT; + mBucketPeriodsMs[EXEMPTED_INDEX] = Math.max( + mAllowedTimePerPeriodMs[EXEMPTED_INDEX], + Math.min(MAX_PERIOD_MS, WINDOW_SIZE_EXEMPTED_MS)); + mBucketPeriodsMs[ACTIVE_INDEX] = Math.max( + mAllowedTimePerPeriodMs[ACTIVE_INDEX], + Math.min(MAX_PERIOD_MS, WINDOW_SIZE_ACTIVE_MS)); + mBucketPeriodsMs[WORKING_INDEX] = Math.max( + mAllowedTimePerPeriodMs[WORKING_INDEX], + Math.min(MAX_PERIOD_MS, WINDOW_SIZE_WORKING_MS)); + mBucketPeriodsMs[FREQUENT_INDEX] = Math.max( + mAllowedTimePerPeriodMs[FREQUENT_INDEX], + Math.min(MAX_PERIOD_MS, WINDOW_SIZE_FREQUENT_MS)); + } - /** - * How many additional sessions to give an app for each accepted quota bump. - */ - public int QUOTA_BUMP_ADDITIONAL_SESSION_COUNT = - DEFAULT_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT; + void adjustDefaultEjLimits() { + EJ_LIMIT_WORKING_MS = DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS; + EJ_TOP_APP_TIME_CHUNK_SIZE_MS = DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS; + EJ_REWARD_INTERACTION_MS = DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS; - /** - * The rolling window size within which to accept and apply quota bump events. - */ - public long QUOTA_BUMP_WINDOW_SIZE_MS = DEFAULT_QUOTA_BUMP_WINDOW_SIZE_MS; + // The limit must be in the range [15 minutes, active limit]. + mEJLimitsMs[WORKING_INDEX] = Math.max(15 * MINUTE_IN_MILLIS, + Math.min(mEJLimitsMs[ACTIVE_INDEX], EJ_LIMIT_WORKING_MS)); - /** - * The maximum number of quota bumps to accept and apply within the - * {@link #QUOTA_BUMP_WINDOW_SIZE_MS window}. - */ - public int QUOTA_BUMP_LIMIT = DEFAULT_QUOTA_BUMP_LIMIT; + // Limit interaction reward to be in the range [5 seconds, 15 minutes] per event. + mEJRewardInteractionMs = Math.min(15 * MINUTE_IN_MILLIS, + Math.max(5 * SECOND_IN_MILLIS, EJ_REWARD_INTERACTION_MS)); + + // Limit chunking to be in the range [1 millisecond, 15 minutes] per event. + long newChunkSizeMs = Math.min(15 * MINUTE_IN_MILLIS, + Math.max(1, EJ_TOP_APP_TIME_CHUNK_SIZE_MS)); + mEJTopAppTimeChunkSizeMs = newChunkSizeMs; + if (mEJTopAppTimeChunkSizeMs < mEJRewardTopAppMs) { + // Not making chunk sizes and top rewards to be the upper/lower + // limits of the other to allow trying different policies. Just log + // the discrepancy. + Slog.w(TAG, "EJ top app time chunk less than reward: " + + mEJTopAppTimeChunkSizeMs + " vs " + mEJRewardTopAppMs); + } + } public void processConstantLocked(@NonNull DeviceConfig.Properties properties, @NonNull String key) { @@ -3650,14 +3581,6 @@ public final class QuotaController extends StateController { updateEJLimitConstantsLocked(); break; - case KEY_QUOTA_BUMP_ADDITIONAL_DURATION_MS: - case KEY_QUOTA_BUMP_ADDITIONAL_JOB_COUNT: - case KEY_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT: - case KEY_QUOTA_BUMP_WINDOW_SIZE_MS: - case KEY_QUOTA_BUMP_LIMIT: - updateQuotaBumpConstantsLocked(); - break; - case KEY_MAX_JOB_COUNT_EXEMPTED: MAX_JOB_COUNT_EXEMPTED = properties.getInt(key, DEFAULT_MAX_JOB_COUNT_EXEMPTED); int newExemptedMaxJobCount = @@ -3790,7 +3713,9 @@ public final class QuotaController extends StateController { case KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS: // We don't need to re-evaluate execution stats or constraint status for this. EJ_TOP_APP_TIME_CHUNK_SIZE_MS = - properties.getLong(key, DEFAULT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS); + properties.getLong(key, Flags.adjustQuotaDefaultConstants() + ? DEFAULT_CURRENT_EJ_TOP_APP_TIME_CHUNK_SIZE_MS : + DEFAULT_LEGACY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS); // Limit chunking to be in the range [1 millisecond, 15 minutes] per event. long newChunkSizeMs = Math.min(15 * MINUTE_IN_MILLIS, Math.max(1, EJ_TOP_APP_TIME_CHUNK_SIZE_MS)); @@ -3826,7 +3751,9 @@ public final class QuotaController extends StateController { case KEY_EJ_REWARD_INTERACTION_MS: // We don't need to re-evaluate execution stats or constraint status for this. EJ_REWARD_INTERACTION_MS = - properties.getLong(key, DEFAULT_EJ_REWARD_INTERACTION_MS); + properties.getLong(key, Flags.adjustQuotaDefaultConstants() + ? DEFAULT_CURRENT_EJ_REWARD_INTERACTION_MS : + DEFAULT_LEGACY_EJ_REWARD_INTERACTION_MS); // Limit interaction reward to be in the range [5 seconds, 15 minutes] per // event. mEJRewardInteractionMs = Math.min(15 * MINUTE_IN_MILLIS, @@ -3900,14 +3827,23 @@ public final class QuotaController extends StateController { MAX_EXECUTION_TIME_MS = properties.getLong(KEY_MAX_EXECUTION_TIME_MS, DEFAULT_MAX_EXECUTION_TIME_MS); WINDOW_SIZE_EXEMPTED_MS = properties.getLong(KEY_WINDOW_SIZE_EXEMPTED_MS, - DEFAULT_WINDOW_SIZE_EXEMPTED_MS); + Flags.adjustQuotaDefaultConstants() + ? DEFAULT_CURRENT_WINDOW_SIZE_EXEMPTED_MS : + DEFAULT_LEGACY_WINDOW_SIZE_EXEMPTED_MS); WINDOW_SIZE_ACTIVE_MS = properties.getLong(KEY_WINDOW_SIZE_ACTIVE_MS, - DEFAULT_WINDOW_SIZE_ACTIVE_MS); + Flags.adjustQuotaDefaultConstants() + ? DEFAULT_CURRENT_WINDOW_SIZE_ACTIVE_MS : + DEFAULT_LEGACY_WINDOW_SIZE_ACTIVE_MS); WINDOW_SIZE_WORKING_MS = - properties.getLong(KEY_WINDOW_SIZE_WORKING_MS, DEFAULT_WINDOW_SIZE_WORKING_MS); + properties.getLong(KEY_WINDOW_SIZE_WORKING_MS, + Flags.adjustQuotaDefaultConstants() + ? DEFAULT_CURRENT_WINDOW_SIZE_WORKING_MS : + DEFAULT_LEGACY_WINDOW_SIZE_WORKING_MS); WINDOW_SIZE_FREQUENT_MS = properties.getLong(KEY_WINDOW_SIZE_FREQUENT_MS, - DEFAULT_WINDOW_SIZE_FREQUENT_MS); + Flags.adjustQuotaDefaultConstants() + ? DEFAULT_CURRENT_WINDOW_SIZE_FREQUENT_MS : + DEFAULT_LEGACY_WINDOW_SIZE_FREQUENT_MS); WINDOW_SIZE_RARE_MS = properties.getLong(KEY_WINDOW_SIZE_RARE_MS, DEFAULT_WINDOW_SIZE_RARE_MS); WINDOW_SIZE_RESTRICTED_MS = @@ -4078,7 +4014,9 @@ public final class QuotaController extends StateController { EJ_LIMIT_ACTIVE_MS = properties.getLong( KEY_EJ_LIMIT_ACTIVE_MS, DEFAULT_EJ_LIMIT_ACTIVE_MS); EJ_LIMIT_WORKING_MS = properties.getLong( - KEY_EJ_LIMIT_WORKING_MS, DEFAULT_EJ_LIMIT_WORKING_MS); + KEY_EJ_LIMIT_WORKING_MS, Flags.adjustQuotaDefaultConstants() + ? DEFAULT_CURRENT_EJ_LIMIT_WORKING_MS : + DEFAULT_LEGACY_EJ_LIMIT_WORKING_MS); EJ_LIMIT_FREQUENT_MS = properties.getLong( KEY_EJ_LIMIT_FREQUENT_MS, DEFAULT_EJ_LIMIT_FREQUENT_MS); EJ_LIMIT_RARE_MS = properties.getLong( @@ -4156,65 +4094,6 @@ public final class QuotaController extends StateController { } } - private void updateQuotaBumpConstantsLocked() { - if (mQuotaBumpConstantsUpdated) { - return; - } - mQuotaBumpConstantsUpdated = true; - - // Query the values as an atomic set. - final DeviceConfig.Properties properties = DeviceConfig.getProperties( - DeviceConfig.NAMESPACE_JOB_SCHEDULER, - KEY_QUOTA_BUMP_ADDITIONAL_DURATION_MS, - KEY_QUOTA_BUMP_ADDITIONAL_JOB_COUNT, KEY_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT, - KEY_QUOTA_BUMP_WINDOW_SIZE_MS, KEY_QUOTA_BUMP_LIMIT); - QUOTA_BUMP_ADDITIONAL_DURATION_MS = properties.getLong( - KEY_QUOTA_BUMP_ADDITIONAL_DURATION_MS, - DEFAULT_QUOTA_BUMP_ADDITIONAL_DURATION_MS); - QUOTA_BUMP_ADDITIONAL_JOB_COUNT = properties.getInt( - KEY_QUOTA_BUMP_ADDITIONAL_JOB_COUNT, DEFAULT_QUOTA_BUMP_ADDITIONAL_JOB_COUNT); - QUOTA_BUMP_ADDITIONAL_SESSION_COUNT = properties.getInt( - KEY_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT, - DEFAULT_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT); - QUOTA_BUMP_WINDOW_SIZE_MS = properties.getLong( - KEY_QUOTA_BUMP_WINDOW_SIZE_MS, DEFAULT_QUOTA_BUMP_WINDOW_SIZE_MS); - QUOTA_BUMP_LIMIT = properties.getInt( - KEY_QUOTA_BUMP_LIMIT, DEFAULT_QUOTA_BUMP_LIMIT); - - // The window must be in the range [1 hour, 24 hours]. - long newWindowSizeMs = Math.max(HOUR_IN_MILLIS, - Math.min(MAX_PERIOD_MS, QUOTA_BUMP_WINDOW_SIZE_MS)); - if (mQuotaBumpWindowSizeMs != newWindowSizeMs) { - mQuotaBumpWindowSizeMs = newWindowSizeMs; - mShouldReevaluateConstraints = true; - } - // The limit must be nonnegative. - int newLimit = Math.max(0, QUOTA_BUMP_LIMIT); - if (mQuotaBumpLimit != newLimit) { - mQuotaBumpLimit = newLimit; - mShouldReevaluateConstraints = true; - } - // The job count must be nonnegative. - int newJobAddition = Math.max(0, QUOTA_BUMP_ADDITIONAL_JOB_COUNT); - if (mQuotaBumpAdditionalJobCount != newJobAddition) { - mQuotaBumpAdditionalJobCount = newJobAddition; - mShouldReevaluateConstraints = true; - } - // The session count must be nonnegative. - int newSessionAddition = Math.max(0, QUOTA_BUMP_ADDITIONAL_SESSION_COUNT); - if (mQuotaBumpAdditionalSessionCount != newSessionAddition) { - mQuotaBumpAdditionalSessionCount = newSessionAddition; - mShouldReevaluateConstraints = true; - } - // The additional duration must be in the range [0, 10 minutes]. - long newAdditionalDuration = Math.max(0, - Math.min(10 * MINUTE_IN_MILLIS, QUOTA_BUMP_ADDITIONAL_DURATION_MS)); - if (mQuotaBumpAdditionalDurationMs != newAdditionalDuration) { - mQuotaBumpAdditionalDurationMs = newAdditionalDuration; - mShouldReevaluateConstraints = true; - } - } - private void dump(IndentingPrintWriter pw) { pw.println(); pw.println("QuotaController:"); @@ -4277,15 +4156,6 @@ public final class QuotaController extends StateController { EJ_GRACE_PERIOD_TEMP_ALLOWLIST_MS).println(); pw.print(KEY_EJ_GRACE_PERIOD_TOP_APP_MS, EJ_GRACE_PERIOD_TOP_APP_MS).println(); - pw.print(KEY_QUOTA_BUMP_ADDITIONAL_DURATION_MS, - QUOTA_BUMP_ADDITIONAL_DURATION_MS).println(); - pw.print(KEY_QUOTA_BUMP_ADDITIONAL_JOB_COUNT, - QUOTA_BUMP_ADDITIONAL_JOB_COUNT).println(); - pw.print(KEY_QUOTA_BUMP_ADDITIONAL_SESSION_COUNT, - QUOTA_BUMP_ADDITIONAL_SESSION_COUNT).println(); - pw.print(KEY_QUOTA_BUMP_WINDOW_SIZE_MS, QUOTA_BUMP_WINDOW_SIZE_MS).println(); - pw.print(KEY_QUOTA_BUMP_LIMIT, QUOTA_BUMP_LIMIT).println(); - pw.decreaseIndent(); } @@ -4503,37 +4373,19 @@ public final class QuotaController extends StateController { return mQcConstants; } - @VisibleForTesting - long getQuotaBumpAdditionDurationMs() { - return mQuotaBumpAdditionalDurationMs; - } - - @VisibleForTesting - int getQuotaBumpAdditionJobCount() { - return mQuotaBumpAdditionalJobCount; - } - - @VisibleForTesting - int getQuotaBumpAdditionSessionCount() { - return mQuotaBumpAdditionalSessionCount; - } - - @VisibleForTesting - int getQuotaBumpLimit() { - return mQuotaBumpLimit; - } - - @VisibleForTesting - long getQuotaBumpWindowSizeMs() { - return mQuotaBumpWindowSizeMs; - } - //////////////////////////// DATA DUMP ////////////////////////////// @NeverCompile // Avoid size overhead of debugging code. @Override public void dumpControllerStateLocked(final IndentingPrintWriter pw, final Predicate predicate) { + pw.println("Flags: "); + pw.println(" " + Flags.FLAG_ADJUST_QUOTA_DEFAULT_CONSTANTS + + ": " + Flags.adjustQuotaDefaultConstants()); + pw.println(" " + Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_FGS_JOBS + + ": " + Flags.enforceQuotaPolicyToFgsJobs()); + pw.println(); + pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis()); pw.println(); diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java index 6265d9bb815f77d449d120562b8f520b0e6f9e25..a8641ae4350952a3c93b87bb573539475273b220 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java @@ -629,14 +629,15 @@ public class AppIdleHistory { } /** - * Returns the index in the arrays of screenTimeThresholds and elapsedTimeThresholds - * that corresponds to how long since the app was used. + * Returns the index in the array of elapsedTimeThresholds that corresponds to + * how long since the app was used. * @param packageName * @param userId * @param elapsedRealtime current time - * @param screenTimeThresholds Array of screen times, in ascending order, first one is 0 + * @param screenTimeThresholds Array of screen times, in ascending order, + * first one is 0 (this will not be used any more) * @param elapsedTimeThresholds Array of elapsed time, in ascending order, first one is 0 - * @return The index whose values the app's used time exceeds (in both arrays) or {@code -1} to + * @return The index whose values the app's used time exceeds or {@code -1} to * indicate that the app has never been used. */ int getThresholdIndex(String packageName, int userId, long elapsedRealtime, @@ -646,7 +647,7 @@ public class AppIdleHistory { elapsedRealtime, false); // If we don't have any state for the app, assume never used if (appUsageHistory == null || appUsageHistory.lastUsedElapsedTime < 0 - || appUsageHistory.lastUsedScreenTime < 0) { + || (!Flags.screenTimeBypass() && appUsageHistory.lastUsedScreenTime < 0)) { return -1; } @@ -659,7 +660,7 @@ public class AppIdleHistory { if (DEBUG) Slog.d(TAG, packageName + " screenOn=" + screenOnDelta + ", elapsed=" + elapsedDelta); for (int i = screenTimeThresholds.length - 1; i >= 0; i--) { - if (screenOnDelta >= screenTimeThresholds[i] + if ((Flags.screenTimeBypass() || screenOnDelta >= screenTimeThresholds[i]) && elapsedDelta >= elapsedTimeThresholds[i]) { return i; } diff --git a/cmds/bootanimation/OWNERS b/cmds/bootanimation/OWNERS index b6fb007bea52eefcbd182385f2c1a583f177b1fb..2eda44dabec3d4a687361600f3cf33127081f7e0 100644 --- a/cmds/bootanimation/OWNERS +++ b/cmds/bootanimation/OWNERS @@ -1,3 +1,4 @@ dupin@google.com shanh@google.com jreck@google.com +rahulbanerjee@google.com \ No newline at end of file diff --git a/core/api/current.txt b/core/api/current.txt index ebc534f6e39162a73920a7df8a2789bc30b18a33..ff203848fa3a2ed470fc476be7b9c11d88d8b660 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -239,6 +239,7 @@ package android { field @Deprecated public static final String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS"; field public static final String PROVIDE_OWN_AUTOFILL_SUGGESTIONS = "android.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS"; field public static final String PROVIDE_REMOTE_CREDENTIALS = "android.permission.PROVIDE_REMOTE_CREDENTIALS"; + field @FlaggedApi("android.security.aapm_api") public static final String QUERY_ADVANCED_PROTECTION_MODE = "android.permission.QUERY_ADVANCED_PROTECTION_MODE"; field public static final String QUERY_ALL_PACKAGES = "android.permission.QUERY_ALL_PACKAGES"; field public static final String READ_ASSISTANT_APP_SEARCH_DATA = "android.permission.READ_ASSISTANT_APP_SEARCH_DATA"; field public static final String READ_BASIC_PHONE_STATE = "android.permission.READ_BASIC_PHONE_STATE"; @@ -8781,7 +8782,6 @@ package android.app.admin { package android.app.appfunctions { @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager { - method @Deprecated @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", "android.permission.EXECUTE_APP_FUNCTIONS"}, conditional=true) public void executeAppFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", "android.permission.EXECUTE_APP_FUNCTIONS"}, conditional=true) public void executeAppFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.concurrent.Executor, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer); method public void isAppFunctionEnabled(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); method public void setAppFunctionEnabled(@NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver); @@ -8793,9 +8793,7 @@ package android.app.appfunctions { @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public abstract class AppFunctionService extends android.app.Service { ctor public AppFunctionService(); method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent); - method @Deprecated @MainThread public void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.function.Consumer); - method @Deprecated @MainThread public void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer); - method @MainThread public void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull String, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer); + method @MainThread public abstract void onExecuteFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull String, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer); field @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService"; } @@ -10804,6 +10802,7 @@ package android.content { field public static final String ACCESSIBILITY_SERVICE = "accessibility"; field public static final String ACCOUNT_SERVICE = "account"; field public static final String ACTIVITY_SERVICE = "activity"; + field @FlaggedApi("android.security.aapm_api") public static final String ADVANCED_PROTECTION_SERVICE = "advanced_protection"; field public static final String ALARM_SERVICE = "alarm"; field public static final String APPWIDGET_SERVICE = "appwidget"; field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String APP_FUNCTION_SERVICE = "app_function"; @@ -10865,6 +10864,7 @@ package android.content { field public static final String IPSEC_SERVICE = "ipsec"; field public static final String JOB_SCHEDULER_SERVICE = "jobscheduler"; field public static final String KEYGUARD_SERVICE = "keyguard"; + field @FlaggedApi("android.security.keystore_grant_api") public static final String KEYSTORE_SERVICE = "keystore"; field public static final String LAUNCHER_APPS_SERVICE = "launcherapps"; field @UiContext public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater"; field public static final String LOCALE_SERVICE = "locale"; @@ -16104,6 +16104,7 @@ package android.graphics { enum_constant public static final android.graphics.ColorSpace.Named CIE_LAB; enum_constant public static final android.graphics.ColorSpace.Named CIE_XYZ; enum_constant public static final android.graphics.ColorSpace.Named DCI_P3; + enum_constant @FlaggedApi("com.android.graphics.flags.display_bt2020_colorspace") public static final android.graphics.ColorSpace.Named DISPLAY_BT2020; enum_constant public static final android.graphics.ColorSpace.Named DISPLAY_P3; enum_constant public static final android.graphics.ColorSpace.Named EXTENDED_SRGB; enum_constant public static final android.graphics.ColorSpace.Named LINEAR_EXTENDED_SRGB; @@ -18620,6 +18621,7 @@ package android.hardware { field public static final int DATASPACE_BT709 = 281083904; // 0x10c10000 field public static final int DATASPACE_DCI_P3 = 155844608; // 0x94a0000 field public static final int DATASPACE_DEPTH = 4096; // 0x1000 + field @FlaggedApi("com.android.graphics.flags.display_bt2020_colorspace") public static final int DATASPACE_DISPLAY_BT2020 = 142999552; // 0x8860000 field public static final int DATASPACE_DISPLAY_P3 = 143261696; // 0x88a0000 field public static final int DATASPACE_DYNAMIC_DEPTH = 4098; // 0x1002 field public static final int DATASPACE_HEIF = 4100; // 0x1004 @@ -32782,6 +32784,8 @@ package android.os { public class Build { ctor public Build(); method @NonNull public static java.util.List getFingerprintedPartitions(); + method @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static int getMajorSdkVersion(int); + method @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static int getMinorSdkVersion(int); method public static String getRadioVersion(); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public static String getSerial(); field public static final String BOARD; @@ -32878,6 +32882,41 @@ package android.os { } @FlaggedApi("android.sdk.major_minor_versioning_scheme") public static class Build.VERSION_CODES_FULL { + field public static final int BASE = 100000; // 0x186a0 + field public static final int BASE_1_1 = 200000; // 0x30d40 + field public static final int CUPCAKE = 300000; // 0x493e0 + field public static final int DONUT = 400000; // 0x61a80 + field public static final int ECLAIR = 500000; // 0x7a120 + field public static final int ECLAIR_0_1 = 600000; // 0x927c0 + field public static final int ECLAIR_MR1 = 700000; // 0xaae60 + field public static final int FROYO = 800000; // 0xc3500 + field public static final int GINGERBREAD = 900000; // 0xdbba0 + field public static final int GINGERBREAD_MR1 = 1000000; // 0xf4240 + field public static final int HONEYCOMB = 1100000; // 0x10c8e0 + field public static final int HONEYCOMB_MR1 = 1200000; // 0x124f80 + field public static final int HONEYCOMB_MR2 = 1300000; // 0x13d620 + field public static final int ICE_CREAM_SANDWICH = 1400000; // 0x155cc0 + field public static final int ICE_CREAM_SANDWICH_MR1 = 1500000; // 0x16e360 + field public static final int JELLY_BEAN = 1600000; // 0x186a00 + field public static final int JELLY_BEAN_MR1 = 1700000; // 0x19f0a0 + field public static final int JELLY_BEAN_MR2 = 1800000; // 0x1b7740 + field public static final int KITKAT = 1900000; // 0x1cfde0 + field public static final int KITKAT_WATCH = 2000000; // 0x1e8480 + field public static final int LOLLIPOP = 2100000; // 0x200b20 + field public static final int LOLLIPOP_MR1 = 2200000; // 0x2191c0 + field public static final int M = 2300000; // 0x231860 + field public static final int N = 2400000; // 0x249f00 + field public static final int N_MR1 = 2500000; // 0x2625a0 + field public static final int O = 2600000; // 0x27ac40 + field public static final int O_MR1 = 2700000; // 0x2932e0 + field public static final int P = 2800000; // 0x2ab980 + field public static final int Q = 2900000; // 0x2c4020 + field public static final int R = 3000000; // 0x2dc6c0 + field public static final int S = 3100000; // 0x2f4d60 + field public static final int S_V2 = 3200000; // 0x30d400 + field public static final int TIRAMISU = 3300000; // 0x325aa0 + field public static final int UPSIDE_DOWN_CAKE = 3400000; // 0x33e140 + field public static final int VANILLA_ICE_CREAM = 3500000; // 0x3567e0 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -39697,6 +39736,20 @@ package android.security { } +package android.security.advancedprotection { + + @FlaggedApi("android.security.aapm_api") public class AdvancedProtectionManager { + method @RequiresPermission(android.Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE) public boolean isAdvancedProtectionEnabled(); + method @RequiresPermission(android.Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE) public void registerAdvancedProtectionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.security.advancedprotection.AdvancedProtectionManager.Callback); + method @RequiresPermission(android.Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE) public void unregisterAdvancedProtectionCallback(@NonNull android.security.advancedprotection.AdvancedProtectionManager.Callback); + } + + @FlaggedApi("android.security.aapm_api") public static interface AdvancedProtectionManager.Callback { + method public void onAdvancedProtectionChanged(boolean); + } + +} + package android.security.identity { public class AccessControlProfile { @@ -40114,6 +40167,14 @@ package android.security.keystore { method @NonNull public android.security.keystore.KeyProtection.Builder setUserPresenceRequired(boolean); } + @FlaggedApi("android.security.keystore_grant_api") public class KeyStoreManager { + method @NonNull public java.util.List getGrantedCertificateChainFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException; + method @NonNull public java.security.Key getGrantedKeyFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException; + method @NonNull public java.security.KeyPair getGrantedKeyPairFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException; + method public long grantKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException; + method public void revokeKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException; + } + public class SecureKeyImportUnavailableException extends java.security.ProviderException { ctor public SecureKeyImportUnavailableException(); ctor public SecureKeyImportUnavailableException(String); @@ -43849,8 +43910,8 @@ package android.telephony { field public static final String KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrq_thresholds_int_array"; field public static final String KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY = "5g_nr_sssinr_thresholds_int_array"; field public static final String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool"; - field @FlaggedApi("com.android.internal.telephony.flags.show_call_id_and_call_waiting_in_additional_settings_menu") public static final String KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL = "additional_settings_caller_id_visibility_bool"; - field @FlaggedApi("com.android.internal.telephony.flags.show_call_id_and_call_waiting_in_additional_settings_menu") public static final String KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL = "additional_settings_call_waiting_visibility_bool"; + field public static final String KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL = "additional_settings_caller_id_visibility_bool"; + field public static final String KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL = "additional_settings_call_waiting_visibility_bool"; field public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool"; field public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call"; field public static final String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool"; @@ -43933,7 +43994,7 @@ package android.telephony { field public static final String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array"; field public static final String KEY_CDMA_ROAMING_MODE_INT = "cdma_roaming_mode_int"; field public static final String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array"; - field @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final String KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY = "cellular_service_capabilities_int_array"; + field public static final String KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY = "cellular_service_capabilities_int_array"; field public static final String KEY_CELLULAR_USAGE_SETTING_INT = "cellular_usage_setting_int"; field public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL = "check_pricing_with_carrier_data_roaming_bool"; field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_BOOL = "ci_action_on_sys_update_bool"; @@ -45909,6 +45970,7 @@ package android.telephony { method public byte[] getPdu(); method public int getProtocolIdentifier(); method public String getPseudoSubject(); + method @FlaggedApi("com.android.internal.telephony.flags.support_sms_over_ims_apis") @Nullable public String getRecipientAddress(); method public String getServiceCenterAddress(); method public int getStatus(); method public int getStatusOnIcc(); @@ -45970,7 +46032,7 @@ package android.telephony { method @Nullable public String getMncString(); method @Deprecated public String getNumber(); method public int getPortIndex(); - method @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") @NonNull public java.util.Set getServiceCapabilities(); + method @NonNull public java.util.Set getServiceCapabilities(); method public int getSimSlotIndex(); method public int getSubscriptionId(); method public int getSubscriptionType(); @@ -46053,9 +46115,9 @@ package android.telephony { field public static final int PHONE_NUMBER_SOURCE_CARRIER = 2; // 0x2 field public static final int PHONE_NUMBER_SOURCE_IMS = 3; // 0x3 field public static final int PHONE_NUMBER_SOURCE_UICC = 1; // 0x1 - field @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final int SERVICE_CAPABILITY_DATA = 3; // 0x3 - field @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final int SERVICE_CAPABILITY_SMS = 2; // 0x2 - field @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public static final int SERVICE_CAPABILITY_VOICE = 1; // 0x1 + field public static final int SERVICE_CAPABILITY_DATA = 3; // 0x3 + field public static final int SERVICE_CAPABILITY_SMS = 2; // 0x2 + field public static final int SERVICE_CAPABILITY_VOICE = 1; // 0x1 field public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0; // 0x0 field public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1; // 0x1 field public static final int USAGE_SETTING_DATA_CENTRIC = 2; // 0x2 @@ -46304,8 +46366,8 @@ package android.telephony { method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataEnabled(); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataEnabledForReason(int); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataRoamingEnabled(); - method @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public boolean isDeviceSmsCapable(); - method @FlaggedApi("com.android.internal.telephony.flags.data_only_cellular_service") public boolean isDeviceVoiceCapable(); + method public boolean isDeviceSmsCapable(); + method public boolean isDeviceVoiceCapable(); method public boolean isEmergencyNumber(@NonNull String); method public boolean isHearingAidCompatibilitySupported(); method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isManualNetworkSelectionAllowed(); @@ -46364,7 +46426,7 @@ package android.telephony { field public static final String ACTION_MULTI_SIM_CONFIG_CHANGED = "android.telephony.action.MULTI_SIM_CONFIG_CHANGED"; field public static final String ACTION_NETWORK_COUNTRY_CHANGED = "android.telephony.action.NETWORK_COUNTRY_CHANGED"; field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; - field @FlaggedApi("com.android.internal.telephony.flags.reset_mobile_network_settings") public static final String ACTION_RESET_MOBILE_NETWORK_SETTINGS = "android.telephony.action.RESET_MOBILE_NETWORK_SETTINGS"; + field public static final String ACTION_RESET_MOBILE_NETWORK_SETTINGS = "android.telephony.action.RESET_MOBILE_NETWORK_SETTINGS"; field public static final String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; field public static final String ACTION_SECRET_CODE = "android.telephony.action.SECRET_CODE"; field public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION"; @@ -50944,6 +51006,7 @@ package android.view { method public android.view.Display.Mode[] getSupportedModes(); method @Deprecated public float[] getSupportedRefreshRates(); method @Deprecated public int getWidth(); + method @FlaggedApi("com.android.server.display.feature.flags.enable_has_arr_support") public boolean hasArrSupport(); method public boolean isHdr(); method public boolean isHdrSdrRatioAvailable(); method public boolean isMinimalPostProcessingSupported(); @@ -52177,7 +52240,7 @@ package android.view { method public void clear(); method public void copyFrom(android.view.MotionEvent.PointerCoords); method public float getAxisValue(int); - method @FlaggedApi("com.android.hardware.input.pointer_coords_is_resampled_api") public boolean isResampled(); + method public boolean isResampled(); method public void setAxisValue(int, float); field public float orientation; field public float pressure; @@ -56597,7 +56660,7 @@ package android.view.inputmethod { method public java.util.Map> getShortcutInputMethodsAndSubtypes(); method @Deprecated public void hideSoftInputFromInputMethod(android.os.IBinder, int); method public boolean hideSoftInputFromWindow(android.os.IBinder, int); - method public boolean hideSoftInputFromWindow(android.os.IBinder, int, android.os.ResultReceiver); + method @Deprecated public boolean hideSoftInputFromWindow(android.os.IBinder, int, android.os.ResultReceiver); method @Deprecated public void hideStatusIcon(android.os.IBinder); method public void invalidateInput(@NonNull android.view.View); method public boolean isAcceptingText(); @@ -56621,7 +56684,7 @@ package android.view.inputmethod { method public void showInputMethodAndSubtypeEnabler(@Nullable String); method public void showInputMethodPicker(); method public boolean showSoftInput(android.view.View, int); - method public boolean showSoftInput(android.view.View, int, android.os.ResultReceiver); + method @Deprecated public boolean showSoftInput(android.view.View, int, android.os.ResultReceiver); method @Deprecated public void showSoftInputFromInputMethod(android.os.IBinder, int); method @Deprecated public void showStatusIcon(android.os.IBinder, String, @DrawableRes int); method @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public void startConnectionlessStylusHandwriting(@NonNull android.view.View, @Nullable android.view.inputmethod.CursorAnchorInfo, @NonNull java.util.concurrent.Executor, @NonNull android.view.inputmethod.ConnectionlessHandwritingCallback); @@ -58127,12 +58190,16 @@ package android.webkit { method public abstract String[] getAcceptTypes(); method @Nullable public abstract String getFilenameHint(); method public abstract int getMode(); + method @FlaggedApi("android.webkit.file_system_access") public int getPermissionMode(); method @Nullable public abstract CharSequence getTitle(); method public abstract boolean isCaptureEnabled(); method @Nullable public static android.net.Uri[] parseResult(int, android.content.Intent); field public static final int MODE_OPEN = 0; // 0x0 + field @FlaggedApi("android.webkit.file_system_access") public static final int MODE_OPEN_FOLDER = 2; // 0x2 field public static final int MODE_OPEN_MULTIPLE = 1; // 0x1 field public static final int MODE_SAVE = 3; // 0x3 + field @FlaggedApi("android.webkit.file_system_access") public static final int PERMISSION_MODE_READ = 0; // 0x0 + field @FlaggedApi("android.webkit.file_system_access") public static final int PERMISSION_MODE_READ_WRITE = 1; // 0x1 } public abstract class WebHistoryItem implements java.lang.Cloneable { @@ -58489,7 +58556,7 @@ package android.webkit { method public void setWebViewRenderProcessClient(@Nullable android.webkit.WebViewRenderProcessClient); method @Deprecated public boolean shouldDelayChildPressedState(); method @Deprecated public boolean showFindDialog(@Nullable String, boolean); - method public static void startSafeBrowsing(@NonNull android.content.Context, @Nullable android.webkit.ValueCallback); + method @Deprecated @FlaggedApi("android.webkit.deprecate_start_safe_browsing") public static void startSafeBrowsing(@NonNull android.content.Context, @Nullable android.webkit.ValueCallback); method public void stopLoading(); method public void zoomBy(float); method public boolean zoomIn(); @@ -61684,6 +61751,8 @@ package android.window { public final class BackEvent { ctor public BackEvent(float, float, float, int); + ctor @FlaggedApi("com.android.window.flags.predictive_back_timestamp_api") public BackEvent(float, float, float, int, long); + method @FlaggedApi("com.android.window.flags.predictive_back_timestamp_api") public long getFrameTime(); method @FloatRange(from=0, to=1) public float getProgress(); method public int getSwipeEdge(); method public float getTouchX(); diff --git a/core/api/removed.txt b/core/api/removed.txt index 3c7c0d6e6ea16a8a67fec2f0b35234f0c8d0e2e9..a3cab291a1de0e6d76adf57989418e11f9adcec3 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -82,12 +82,12 @@ package android.database { package android.graphics { @Deprecated public class AvoidXfermode extends android.graphics.Xfermode { - ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); + ctor @Deprecated public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); } - public enum AvoidXfermode.Mode { - enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID; - enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; + @Deprecated public enum AvoidXfermode.Mode { + enum_constant @Deprecated public static final android.graphics.AvoidXfermode.Mode AVOID; + enum_constant @Deprecated public static final android.graphics.AvoidXfermode.Mode TARGET; } public class Canvas { @@ -102,9 +102,9 @@ package android.graphics { } @Deprecated public class LayerRasterizer extends android.graphics.Rasterizer { - ctor public LayerRasterizer(); - method public void addLayer(android.graphics.Paint, float, float); - method public void addLayer(android.graphics.Paint); + ctor @Deprecated public LayerRasterizer(); + method @Deprecated public void addLayer(android.graphics.Paint, float, float); + method @Deprecated public void addLayer(android.graphics.Paint); } public class Paint { @@ -118,7 +118,7 @@ package android.graphics { } @Deprecated public class PixelXorXfermode extends android.graphics.Xfermode { - ctor public PixelXorXfermode(int); + ctor @Deprecated public PixelXorXfermode(int); } public class Rasterizer { @@ -170,14 +170,14 @@ package android.media.tv { package android.net { @Deprecated public class NetworkBadging { - method @NonNull public static android.graphics.drawable.Drawable getWifiIcon(@IntRange(from=0, to=4) int, int, @Nullable android.content.res.Resources.Theme); - field public static final int BADGING_4K = 30; // 0x1e - field public static final int BADGING_HD = 20; // 0x14 - field public static final int BADGING_NONE = 0; // 0x0 - field public static final int BADGING_SD = 10; // 0xa + method @Deprecated @NonNull public static android.graphics.drawable.Drawable getWifiIcon(@IntRange(from=0, to=4) int, int, @Nullable android.content.res.Resources.Theme); + field @Deprecated public static final int BADGING_4K = 30; // 0x1e + field @Deprecated public static final int BADGING_HD = 20; // 0x14 + field @Deprecated public static final int BADGING_NONE = 0; // 0x0 + field @Deprecated public static final int BADGING_SD = 10; // 0xa } - @IntDef({0x0, 0xa, 0x14, 0x1e}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NetworkBadging.Badging { + @Deprecated @IntDef({0x0, 0xa, 0x14, 0x1e}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NetworkBadging.Badging { } public final class Proxy { @@ -304,14 +304,14 @@ package android.provider { @Deprecated public static final class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns { field @Deprecated public static final String CONTENT_DIRECTORY = "stream_items"; - field public static final String _COUNT = "_count"; - field public static final String _ID = "_id"; + field @Deprecated public static final String _COUNT = "_count"; + field @Deprecated public static final String _ID = "_id"; } @Deprecated public static final class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { field @Deprecated public static final String PHOTO = "photo"; - field public static final String _COUNT = "_count"; - field public static final String _ID = "_id"; + field @Deprecated public static final String _COUNT = "_count"; + field @Deprecated public static final String _ID = "_id"; } @Deprecated protected static interface ContactsContract.StreamItemPhotosColumns { @@ -332,16 +332,16 @@ package android.provider { field @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item"; field @Deprecated public static final android.net.Uri CONTENT_URI; field @Deprecated public static final String MAX_ITEMS = "max_items"; - field public static final String _COUNT = "_count"; - field public static final String _ID = "_id"; + field @Deprecated public static final String _COUNT = "_count"; + field @Deprecated public static final String _ID = "_id"; } @Deprecated public static final class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns { field @Deprecated public static final String CONTENT_DIRECTORY = "photo"; field @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo"; field @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo"; - field public static final String _COUNT = "_count"; - field public static final String _ID = "_id"; + field @Deprecated public static final String _COUNT = "_count"; + field @Deprecated public static final String _ID = "_id"; } @Deprecated protected static interface ContactsContract.StreamItemsColumns { @@ -447,14 +447,14 @@ package android.text.style { package android.util { @Deprecated public class FloatMath { - method public static float ceil(float); - method public static float cos(float); - method public static float exp(float); - method public static float floor(float); - method public static float hypot(float, float); - method public static float pow(float, float); - method public static float sin(float); - method public static float sqrt(float); + method @Deprecated public static float ceil(float); + method @Deprecated public static float cos(float); + method @Deprecated public static float exp(float); + method @Deprecated public static float floor(float); + method @Deprecated public static float hypot(float, float); + method @Deprecated public static float pow(float, float); + method @Deprecated public static float sin(float); + method @Deprecated public static float sqrt(float); } } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 49b711b8b013f6cd76e619b883ffeffe31b48b21..207f4b57e8bf9d5ac6d794fdd09c8bc97c757799 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -362,6 +362,7 @@ package android { field public static final String SERIAL_PORT = "android.permission.SERIAL_PORT"; field @FlaggedApi("android.security.fsverity_api") public static final String SETUP_FSVERITY = "android.permission.SETUP_FSVERITY"; field public static final String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER"; + field @FlaggedApi("android.security.aapm_api") public static final String SET_ADVANCED_PROTECTION_MODE = "android.permission.SET_ADVANCED_PROTECTION_MODE"; field public static final String SET_CLIP_SOURCE = "android.permission.SET_CLIP_SOURCE"; field public static final String SET_DEFAULT_ACCOUNT_FOR_CONTACTS = "android.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS"; field public static final String SET_HARMFUL_APP_WARNINGS = "android.permission.SET_HARMFUL_APP_WARNINGS"; @@ -4170,9 +4171,11 @@ package android.content.pm { } public class PackageInstaller { + method @FlaggedApi("android.content.pm.verification_service") @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public final int getVerificationPolicy(); method @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull java.io.File, int) throws android.content.pm.PackageInstaller.PackageParsingException; method @FlaggedApi("android.content.pm.read_install_info") @NonNull public android.content.pm.PackageInstaller.InstallInfo readInstallInfo(@NonNull android.os.ParcelFileDescriptor, @Nullable String, int) throws android.content.pm.PackageInstaller.PackageParsingException; method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean); + method @FlaggedApi("android.content.pm.verification_service") @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public final boolean setVerificationPolicy(int); field public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL"; field public static final String ACTION_CONFIRM_PRE_APPROVAL = "android.content.pm.action.CONFIRM_PRE_APPROVAL"; field public static final int DATA_LOADER_TYPE_INCREMENTAL = 2; // 0x2 @@ -4183,12 +4186,20 @@ package android.content.pm { field @FlaggedApi("android.content.pm.archiving") public static final String EXTRA_DELETE_FLAGS = "android.content.pm.extra.DELETE_FLAGS"; field public static final String EXTRA_LEGACY_STATUS = "android.content.pm.extra.LEGACY_STATUS"; field @Deprecated public static final String EXTRA_RESOLVED_BASE_PATH = "android.content.pm.extra.RESOLVED_BASE_PATH"; + field @FlaggedApi("android.content.pm.verification_service") public static final String EXTRA_VERIFICATION_FAILURE_REASON = "android.content.pm.extra.VERIFICATION_FAILURE_REASON"; field public static final int LOCATION_DATA_APP = 0; // 0x0 field public static final int LOCATION_MEDIA_DATA = 2; // 0x2 field public static final int LOCATION_MEDIA_OBB = 1; // 0x1 field public static final int REASON_CONFIRM_PACKAGE_CHANGE = 0; // 0x0 field public static final int REASON_OWNERSHIP_CHANGED = 1; // 0x1 field public static final int REASON_REMIND_OWNERSHIP = 2; // 0x2 + field @FlaggedApi("android.content.pm.verification_service") public static final int VERIFICATION_FAILED_REASON_NETWORK_UNAVAILABLE = 1; // 0x1 + field @FlaggedApi("android.content.pm.verification_service") public static final int VERIFICATION_FAILED_REASON_PACKAGE_BLOCKED = 2; // 0x2 + field @FlaggedApi("android.content.pm.verification_service") public static final int VERIFICATION_FAILED_REASON_UNKNOWN = 0; // 0x0 + field @FlaggedApi("android.content.pm.verification_service") public static final int VERIFICATION_POLICY_BLOCK_FAIL_CLOSED = 3; // 0x3 + field @FlaggedApi("android.content.pm.verification_service") public static final int VERIFICATION_POLICY_BLOCK_FAIL_OPEN = 1; // 0x1 + field @FlaggedApi("android.content.pm.verification_service") public static final int VERIFICATION_POLICY_BLOCK_FAIL_WARN = 2; // 0x2 + field @FlaggedApi("android.content.pm.verification_service") public static final int VERIFICATION_POLICY_NONE = 0; // 0x0 } public static class PackageInstaller.InstallInfo { @@ -4635,12 +4646,13 @@ package android.content.pm.verify.pkg { method @NonNull public android.content.pm.SigningInfo getSigningInfo(); method @NonNull public android.net.Uri getStagedPackageUri(); method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public long getTimeoutTime(); + method public int getVerificationPolicy(); method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationComplete(@NonNull android.content.pm.verify.pkg.VerificationStatus); method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationComplete(@NonNull android.content.pm.verify.pkg.VerificationStatus, @NonNull android.os.PersistableBundle); method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationIncomplete(int); + method @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public boolean setVerificationPolicy(int); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final int VERIFICATION_INCOMPLETE_NETWORK_LIMITED = 2; // 0x2 field public static final int VERIFICATION_INCOMPLETE_NETWORK_UNAVAILABLE = 1; // 0x1 field public static final int VERIFICATION_INCOMPLETE_UNKNOWN = 0; // 0x0 } @@ -7319,6 +7331,7 @@ package android.media { field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_APP_OPS = 8; // 0x8 field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_CLIENT_VOLUME = 16; // 0x10 field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_MASTER = 1; // 0x1 + field @FlaggedApi("android.media.audio.muted_by_port_volume_api") @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_PORT_VOLUME = 64; // 0x40 field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_STREAM_MUTED = 4; // 0x4 field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_STREAM_VOLUME = 2; // 0x2 field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int MUTED_BY_VOLUME_SHAPER = 32; // 0x20 @@ -12321,6 +12334,14 @@ package android.security { } +package android.security.advancedprotection { + + @FlaggedApi("android.security.aapm_api") public class AdvancedProtectionManager { + method @RequiresPermission(android.Manifest.permission.SET_ADVANCED_PROTECTION_MODE) public void setAdvancedProtectionEnabled(boolean); + } + +} + package android.security.keystore { public class AndroidKeyStoreProvider extends java.security.Provider { @@ -13104,7 +13125,7 @@ package android.service.notification { method public final void adjustNotification(@NonNull android.service.notification.Adjustment); method public final void adjustNotifications(@NonNull java.util.List); method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int); - method @Deprecated public void onAllowedAdjustmentsChanged(); + method public void onAllowedAdjustmentsChanged(); method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent); method public void onNotificationClicked(@NonNull String); method public void onNotificationDirectReplied(@NonNull String); diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt index bbfa0ec3f3c2e0101beb56b42566464150bce563..78b9994e8fa1a3e4cbaecc5042d3ea2e3855eada 100644 --- a/core/api/system-removed.txt +++ b/core/api/system-removed.txt @@ -7,8 +7,8 @@ package android.app { } @Deprecated public abstract static class AppOpsManager.AppOpsCollector extends android.app.AppOpsManager.OnOpNotedCallback { - ctor public AppOpsManager.AppOpsCollector(); - method @NonNull public java.util.concurrent.Executor getAsyncNotedExecutor(); + ctor @Deprecated public AppOpsManager.AppOpsCollector(); + method @Deprecated @NonNull public java.util.concurrent.Executor getAsyncNotedExecutor(); } public class Notification implements android.os.Parcelable { @@ -207,7 +207,7 @@ package android.service.translation { @Deprecated public static interface TranslationService.OnTranslationResultCallback { method @Deprecated public void onError(); - method public void onTranslationSuccess(@NonNull android.view.translation.TranslationResponse); + method @Deprecated public void onTranslationSuccess(@NonNull android.view.translation.TranslationResponse); } } @@ -261,64 +261,64 @@ package android.telephony.ims { } @Deprecated public final class SipDelegateImsConfiguration implements android.os.Parcelable { - method public boolean containsKey(@NonNull String); - method @NonNull public android.os.PersistableBundle copyBundle(); - method public int describeContents(); - method public boolean getBoolean(@NonNull String, boolean); - method public int getInt(@NonNull String, int); - method @Nullable public String getString(@NonNull String); - method public long getVersion(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator CREATOR; - field public static final String IPTYPE_IPV4 = "IPV4"; - field public static final String IPTYPE_IPV6 = "IPV6"; - field public static final String KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING = "sip_config_auhentication_header_string"; - field public static final String KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING = "sip_config_authentication_nonce_string"; - field public static final String KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING = "sip_config_cellular_network_info_header_string"; - field public static final String KEY_SIP_CONFIG_HOME_DOMAIN_STRING = "sip_config_home_domain_string"; - field public static final String KEY_SIP_CONFIG_IMEI_STRING = "sip_config_imei_string"; - field public static final String KEY_SIP_CONFIG_IPTYPE_STRING = "sip_config_iptype_string"; - field public static final String KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL = "sip_config_is_compact_form_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL = "sip_config_is_gruu_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL = "sip_config_is_ipsec_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL = "sip_config_is_keepalive_enabled_bool"; - field public static final String KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL = "sip_config_is_nat_enabled_bool"; - field public static final String KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT = "sip_config_udp_max_payload_size_int"; - field public static final String KEY_SIP_CONFIG_PATH_HEADER_STRING = "sip_config_path_header_string"; - field public static final String KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_access_network_info_header_string"; - field public static final String KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING = "sip_config_p_associated_uri_header_string"; - field public static final String KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_last_access_network_info_header_string"; - field public static final String KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING = "sip_config_security_verify_header_string"; - field public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING = "sip_config_server_default_ipaddress_string"; - field public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT = "sip_config_server_default_port_int"; - field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT = "sip_config_server_ipsec_client_port_int"; - field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_server_ipsec_old_client_port_int"; - field public static final String KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT = "sip_config_server_ipsec_server_port_int"; - field public static final String KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING = "sip_config_service_route_header_string"; - field public static final String KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING = "sip_config_protocol_type_string"; - field public static final String KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING = "sip_config_ue_default_ipaddress_string"; - field public static final String KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT = "sip_config_ue_default_port_int"; - field public static final String KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT = "sip_config_ue_ipsec_client_port_int"; - field public static final String KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_ue_ipsec_old_client_port_int"; - field public static final String KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT = "sip_config_ue_ipsec_server_port_int"; - field public static final String KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING = "sip_config_ue_private_user_id_string"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING = "sip_config_ue_public_gruu_string"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING = "sip_config_ue_public_ipaddress_with_nat_string"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT = "sip_config_ue_public_port_with_nat_int"; - field public static final String KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING = "sip_config_ue_public_user_id_string"; - field public static final String KEY_SIP_CONFIG_URI_USER_PART_STRING = "sip_config_uri_user_part_string"; - field public static final String KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING = "sip_config_sip_user_agent_header_string"; - field public static final String SIP_TRANSPORT_TCP = "TCP"; - field public static final String SIP_TRANSPORT_UDP = "UDP"; - } - - public static final class SipDelegateImsConfiguration.Builder { - ctor public SipDelegateImsConfiguration.Builder(int); - ctor public SipDelegateImsConfiguration.Builder(@NonNull android.telephony.ims.SipDelegateImsConfiguration); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addBoolean(@NonNull String, boolean); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addInt(@NonNull String, int); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addString(@NonNull String, @NonNull String); - method @NonNull public android.telephony.ims.SipDelegateImsConfiguration build(); + method @Deprecated public boolean containsKey(@NonNull String); + method @Deprecated @NonNull public android.os.PersistableBundle copyBundle(); + method @Deprecated public int describeContents(); + method @Deprecated public boolean getBoolean(@NonNull String, boolean); + method @Deprecated public int getInt(@NonNull String, int); + method @Deprecated @Nullable public String getString(@NonNull String); + method @Deprecated public long getVersion(); + method @Deprecated public void writeToParcel(@NonNull android.os.Parcel, int); + field @Deprecated @NonNull public static final android.os.Parcelable.Creator CREATOR; + field @Deprecated public static final String IPTYPE_IPV4 = "IPV4"; + field @Deprecated public static final String IPTYPE_IPV6 = "IPV6"; + field @Deprecated public static final String KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING = "sip_config_auhentication_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING = "sip_config_authentication_nonce_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING = "sip_config_cellular_network_info_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_HOME_DOMAIN_STRING = "sip_config_home_domain_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_IMEI_STRING = "sip_config_imei_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_IPTYPE_STRING = "sip_config_iptype_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL = "sip_config_is_compact_form_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL = "sip_config_is_gruu_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL = "sip_config_is_ipsec_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL = "sip_config_is_keepalive_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL = "sip_config_is_nat_enabled_bool"; + field @Deprecated public static final String KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT = "sip_config_udp_max_payload_size_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_PATH_HEADER_STRING = "sip_config_path_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_access_network_info_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING = "sip_config_p_associated_uri_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING = "sip_config_p_last_access_network_info_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING = "sip_config_security_verify_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING = "sip_config_server_default_ipaddress_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT = "sip_config_server_default_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT = "sip_config_server_ipsec_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_server_ipsec_old_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT = "sip_config_server_ipsec_server_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING = "sip_config_service_route_header_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING = "sip_config_protocol_type_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING = "sip_config_ue_default_ipaddress_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT = "sip_config_ue_default_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT = "sip_config_ue_ipsec_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT = "sip_config_ue_ipsec_old_client_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT = "sip_config_ue_ipsec_server_port_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING = "sip_config_ue_private_user_id_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING = "sip_config_ue_public_gruu_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING = "sip_config_ue_public_ipaddress_with_nat_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT = "sip_config_ue_public_port_with_nat_int"; + field @Deprecated public static final String KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING = "sip_config_ue_public_user_id_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_URI_USER_PART_STRING = "sip_config_uri_user_part_string"; + field @Deprecated public static final String KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING = "sip_config_sip_user_agent_header_string"; + field @Deprecated public static final String SIP_TRANSPORT_TCP = "TCP"; + field @Deprecated public static final String SIP_TRANSPORT_UDP = "UDP"; + } + + @Deprecated public static final class SipDelegateImsConfiguration.Builder { + ctor @Deprecated public SipDelegateImsConfiguration.Builder(int); + ctor @Deprecated public SipDelegateImsConfiguration.Builder(@NonNull android.telephony.ims.SipDelegateImsConfiguration); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addBoolean(@NonNull String, boolean); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addInt(@NonNull String, int); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration.Builder addString(@NonNull String, @NonNull String); + method @Deprecated @NonNull public android.telephony.ims.SipDelegateImsConfiguration build(); } } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 5e4485c33233f0cc5d367c48e40274ca42554929..1ff8c510b6bf51050347c81092297fbf5dcf359f 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -393,7 +393,9 @@ package android.app { public class NotificationManager { method @FlaggedApi("android.app.modes_api") @NonNull public String addAutomaticZenRule(@NonNull android.app.AutomaticZenRule, boolean); + method @FlaggedApi("android.service.notification.notification_classification") public void allowAssistantAdjustment(@NonNull String); method public void cleanUpCallersAfter(long); + method @FlaggedApi("android.service.notification.notification_classification") public void disallowAssistantAdjustment(@NonNull String); method @FlaggedApi("android.app.modes_api") @NonNull public android.service.notification.ZenPolicy getDefaultZenPolicy(); method public android.content.ComponentName getEffectsSuppressor(); method @FlaggedApi("android.service.notification.notification_classification") @NonNull public java.util.Set getUnsupportedAdjustmentTypes(); @@ -1099,6 +1101,7 @@ package android.content.pm { field public static final long OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT = 265452344L; // 0xfd27b38L field public static final long OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION = 255940284L; // 0xf4156bcL field public static final int RESIZE_MODE_RESIZEABLE = 2; // 0x2 + field public static final long UNIVERSAL_RESIZABLE_BY_DEFAULT = 357141415L; // 0x15498ba7L } public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { diff --git a/core/java/Android.bp b/core/java/Android.bp index 1265de1ebb1572cf7a442f221a640de44e0e4ed6..d12e1bf77e179e66976c91ca095c95f022bfb9dd 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -19,6 +19,7 @@ filegroup { srcs: [ "**/*.java", "**/*.aidl", + ":systemfeatures-gen-srcs", ":framework-nfc-non-updatable-sources", ":messagequeue-gen", ":ranging_stack_mock_initializer", @@ -214,6 +215,9 @@ filegroup { aidl_interface { name: "android.os.hintmanager_aidl", + defaults: [ + "android.hardware.power-aidl", + ], srcs: [ "android/os/IHintManager.aidl", "android/os/IHintSession.aidl", @@ -231,9 +235,6 @@ aidl_interface { enabled: true, }, }, - imports: [ - "android.hardware.power-V5", - ], } aidl_library { @@ -665,3 +666,29 @@ java_library { } // protolog end + +// Whether to enable read-only system feature codegen. +gen_readonly_feature_apis = select(release_flag("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS"), { + true: "true", + false: "false", + default: "false", +}) + +// Generates com.android.internal.pm.RoSystemFeatures, optionally compiling in +// details about fixed system features defined by build flags. When disabled, +// the APIs are simply passthrough stubs with no meaningful side effects. +genrule { + name: "systemfeatures-gen-srcs", + cmd: "$(location systemfeatures-gen-tool) com.android.internal.pm.RoSystemFeatures " + + // --readonly=false (default) makes the codegen an effective no-op passthrough API. + " --readonly=" + gen_readonly_feature_apis + + // For now, only export "android.hardware.type.*" system features APIs. + // TODO(b/203143243): Use an intermediate soong var that aggregates all declared + // RELEASE_SYSTEM_FEATURE_* declarations into a single arg. + " --feature-apis=AUTOMOTIVE,WATCH,TELEVISION,EMBEDDED,PC" + + " > $(out)", + out: [ + "RoSystemFeatures.java", + ], + tools: ["systemfeatures-gen-tool"], +} diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 7273e64846c02a88b18a4d525a26deab95459f98..36fc65a76d53a67608ef7c2861fd2ab16f65859f 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1031,7 +1031,9 @@ public class ActivityManager { | PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL; /** - * All implicit capabilities. There are capabilities that process automatically have. + * All implicit capabilities. This capability set is currently only used for processes under + * active instrumentation. The intent is to allow CTS tests to always have these capabilities + * so that every test doesn't need to launch FGS. * @hide */ @TestApi diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 3bd121a4a19b62d5bfaf424679a49e0c34d12d08..f80121d0c9b6914d4d2e55942a5558e7c3b4b9c4 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -1328,7 +1328,8 @@ public abstract class ActivityManagerInternal { * Add a creator token for all embedded intents (stored as extra) of the given intent. * * @param intent The given intent + * @param creatorPackage the package name of the creator app. * @hide */ - public abstract void addCreatorToken(Intent intent); + public abstract void addCreatorToken(Intent intent, String creatorPackage); } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 0c02ba44fddb0e2ec60774f3bf07aec273ff2b01..e7f4dbc24022dbdd7eee6d2bfeaec34cb32bd370 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3841,6 +3841,18 @@ public final class ActivityThread extends ClientTransactionHandler return activityRecord != null ? activityRecord.activity : null; } + /** + * Returns the most recent created activity that's still running. + */ + @Nullable + public Activity getLastCreatedActivity() { + if (mActivities.isEmpty()) { + return null; + } + + return mActivities.valueAt(mActivities.size() - 1).activity; + } + @Override public ActivityClientRecord getActivityClient(IBinder token) { return mActivities.get(token); @@ -7334,6 +7346,8 @@ public final class ActivityThread extends ClientTransactionHandler } } + VMDebug.setUserId(UserHandle.myUserId()); + VMDebug.addApplication(data.appInfo.packageName); // send up app name; do this *before* waiting for debugger Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, @@ -7856,9 +7870,20 @@ public final class ActivityThread extends ClientTransactionHandler file.getParentFile().mkdirs(); Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); } + + if (ii.packageName != null) { + VMDebug.addApplication(ii.packageName); + } } private void handleFinishInstrumentationWithoutRestart() { + LoadedApk loadedApk = getApplication().mLoadedApk; + // Only remove instrumentation app if this was not a self-testing app. + if (mInstrumentationPackageName != null && loadedApk != null && !mInstrumentationPackageName + .equals(loadedApk.mPackageName)) { + VMDebug.removeApplication(mInstrumentationPackageName); + } + mInstrumentation.onDestroy(); mInstrumentationPackageName = null; mInstrumentationAppDir = null; @@ -8892,6 +8917,11 @@ public final class ActivityThread extends ClientTransactionHandler return false; } + void addApplication(@NonNull Application app) { + mAllApplications.add(app); + VMDebug.addApplication(app.mLoadedApk.mPackageName); + } + @Override public boolean isInDensityCompatMode() { return mDensityCompatMode; diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 3b2aab4591a53f1be964f5b4df8cdadc3c6f9dbf..a7597b4d566d789a16f1f167fe1415d5c98af279 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -84,6 +84,8 @@ interface INotificationManager boolean isImportanceLocked(String pkg, int uid); List getAllowedAssistantAdjustments(String pkg); + void allowAssistantAdjustment(String adjustmentType); + void disallowAssistantAdjustment(String adjustmentType); boolean shouldHideSilentStatusIcons(String callingPkg); void setHideSilentStatusIcons(boolean hide); diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 1df8f63aa402a8725bcdef45adee54f6ff99c149..1e45d6fd16745c0e8eba6ed355401e1b0702d5eb 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -1478,7 +1478,7 @@ public final class LoadedApk { + " package " + mPackageName + ": " + e.toString(), e); } } - mActivityThread.mAllApplications.add(app); + mActivityThread.addApplication(app); mApplication = app; if (!allowDuplicateInstances) { synchronized (sApplications) { diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 8b33417e0a79225a2261cc9e12d5bd13b1c5656d..64aa705447aa987c13751ffd431114ea4b93ba66 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -11176,7 +11176,7 @@ public class Notification implements Parcelable } /** - * A Notification Style used to to define a notification whose expanded state includes + * A Notification Style used to define a notification whose expanded state includes * a highly customizable progress bar with segments, points, a custom tracker icon, * and custom icons at the start and end of the progress bar. * @@ -11296,7 +11296,11 @@ public class Notification implements Parcelable * @see Segment */ public @NonNull ProgressStyle setProgressSegments(@NonNull List progressSegments) { - mProgressSegments = new ArrayList<>(progressSegments.size()); + if (mProgressSegments == null) { + mProgressSegments = new ArrayList<>(); + } + mProgressSegments.clear(); + mProgressSegments.addAll(progressSegments); return this; } diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 4a2b016456f7af7a3dfe51db05656d4054100abd..ebe7b3a4fc51802810c1437440b8a48e3d3adb46 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -38,6 +38,7 @@ import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.text.TextUtils; import android.util.Log; +import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.util.Preconditions; @@ -1369,12 +1370,17 @@ public final class NotificationChannel implements Parcelable { if (sound == null || Uri.EMPTY.equals(sound)) { return null; } - Uri canonicalSound = getCanonicalizedSoundUri(context.getContentResolver(), sound); - if (canonicalSound == null) { - // The content provider does not support canonical uris so we backup the default + try { + Uri canonicalSound = getCanonicalizedSoundUri(context.getContentResolver(), sound); + if (canonicalSound == null) { + // The content provider does not support canonical uris so we backup the default + return Settings.System.DEFAULT_NOTIFICATION_URI; + } + return canonicalSound; + } catch (Exception e) { + Slog.e(TAG, "Cannot find file for sound " + sound + " using default"); return Settings.System.DEFAULT_NOTIFICATION_URI; } - return canonicalSound; } /** diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 41abd68c992435d153d9e5d5f0a3249f2054a407..06bf67c1e86f989ccf069791f66090eee72a63e5 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1790,6 +1790,34 @@ public class NotificationManager { } } + /** + * @hide + */ + @TestApi + @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION) + public void allowAssistantAdjustment(@NonNull String capability) { + INotificationManager service = getService(); + try { + service.allowAssistantAdjustment(capability); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @hide + */ + @TestApi + @FlaggedApi(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION) + public void disallowAssistantAdjustment(@NonNull String capability) { + INotificationManager service = getService(); + try { + service.disallowAssistantAdjustment(capability); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ @TestApi public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String pkg) { diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index d363e19bcc195e63aff54fb2f375a731bb16c105..6e4c28f3eca637dcbc9376c5d2e322da81bd6da2 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -3,50 +3,54 @@ per-file ContextImpl.java = * # ActivityManager -per-file ActivityManager* = file:/services/core/java/com/android/server/am/OWNERS -per-file *ApplicationStartInfo* = file:/services/core/java/com/android/server/am/OWNERS -per-file ApplicationErrorReport* = file:/services/core/java/com/android/server/am/OWNERS -per-file ApplicationExitInfo* = file:/services/core/java/com/android/server/am/OWNERS -per-file Application.java = file:/services/core/java/com/android/server/am/OWNERS -per-file ApplicationLoaders.java = file:/services/core/java/com/android/server/am/OWNERS -per-file ApplicationThreadConstants.java = file:/services/core/java/com/android/server/am/OWNERS -per-file ContentProviderHolder* = file:/services/core/java/com/android/server/am/OWNERS -per-file *ForegroundService* = file:/services/core/java/com/android/server/am/OWNERS -per-file IActivityController.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IActivityManager.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IApplicationThread.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IAppTraceRetriever.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IForegroundServiceObserver.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IInstrumentationWatcher.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IntentService.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IServiceConnection.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IStopUserCallback.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file IUidObserver.aidl = file:/services/core/java/com/android/server/am/OWNERS -per-file LoadedApk.java = file:/services/core/java/com/android/server/am/OWNERS -per-file LocalActivityManager.java = file:/services/core/java/com/android/server/am/OWNERS -per-file PendingIntent* = file:/services/core/java/com/android/server/am/OWNERS -per-file *Process* = file:/services/core/java/com/android/server/am/OWNERS -per-file ProfilerInfo* = file:/services/core/java/com/android/server/am/OWNERS -per-file Service* = file:/services/core/java/com/android/server/am/OWNERS -per-file SystemServiceRegistry.java = file:/services/core/java/com/android/server/am/OWNERS -per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS +per-file ActivityManager* = file:/ACTIVITY_MANAGER_OWNERS +per-file Application.java = file:/ACTIVITY_MANAGER_OWNERS +per-file ApplicationErrorReport* = file:/ACTIVITY_MANAGER_OWNERS +per-file ApplicationLoaders.java = file:/ACTIVITY_MANAGER_OWNERS +per-file ApplicationThreadConstants.java = file:/ACTIVITY_MANAGER_OWNERS +per-file ContentProviderHolder* = file:/ACTIVITY_MANAGER_OWNERS +per-file *ForegroundService* = file:/ACTIVITY_MANAGER_OWNERS +per-file IActivityController.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IActivityManager.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IApplicationThread.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IAppTraceRetriever.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IForegroundServiceObserver.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IInstrumentationWatcher.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IntentService.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IServiceConnection.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IStopUserCallback.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file IUidObserver.aidl = file:/ACTIVITY_MANAGER_OWNERS +per-file LoadedApk.java = file:/ACTIVITY_MANAGER_OWNERS +per-file LocalActivityManager.java = file:/ACTIVITY_MANAGER_OWNERS +per-file PendingIntent* = file:/ACTIVITY_MANAGER_OWNERS +per-file *Process* = file:/ACTIVITY_MANAGER_OWNERS +per-file ProfilerInfo* = file:/ACTIVITY_MANAGER_OWNERS +per-file Service* = file:/ACTIVITY_MANAGER_OWNERS +per-file SystemServiceRegistry.java = file:/ACTIVITY_MANAGER_OWNERS +per-file *UserSwitchObserver* = file:/ACTIVITY_MANAGER_OWNERS + +# UI Automation per-file *UiAutomation* = file:/services/accessibility/OWNERS per-file *UiAutomation* = file:/core/java/android/permission/OWNERS + +# Game Manager per-file GameManager* = file:/GAME_MANAGER_OWNERS per-file GameMode* = file:/GAME_MANAGER_OWNERS per-file GameState* = file:/GAME_MANAGER_OWNERS per-file IGameManager* = file:/GAME_MANAGER_OWNERS per-file IGameMode* = file:/GAME_MANAGER_OWNERS + +# Background Starts per-file BackgroundStartPrivileges.java = file:/BAL_OWNERS per-file activity_manager.aconfig = file:/ACTIVITY_MANAGER_OWNERS # ActivityThread -per-file ActivityThread.java = file:/services/core/java/com/android/server/am/OWNERS +per-file ActivityThread.java = file:/ACTIVITY_MANAGER_OWNERS per-file ActivityThread.java = file:/services/core/java/com/android/server/wm/OWNERS per-file ActivityThread.java = file:RESOURCES_OWNERS # Alarm -per-file *Alarm* = file:/apex/jobscheduler/OWNERS +per-file *Alarm* = file:/apex/jobscheduler/ALARM_OWNERS # AppOps per-file *AppOp* = file:/core/java/android/permission/OWNERS @@ -97,6 +101,9 @@ per-file InstantAppResolveInfo.aidl = file:/services/core/java/com/android/serve # Performance per-file PropertyInvalidatedCache.java = file:/PERFORMANCE_OWNERS +per-file *ApplicationStartInfo* = file:/PERFORMANCE_OWNERS +per-file ApplicationExitInfo* = file:/PERFORMANCE_OWNERS +per-file performance.aconfig = file:/PERFORMANCE_OWNERS # Pinner per-file pinner-client.aconfig = file:/core/java/android/app/pinner/OWNERS diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index ea4148c8ffa19d712a43c26ce01d6fa27b946c75..bd26db55052bd802028f5295b643be945f785871 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -76,7 +76,6 @@ import android.companion.virtual.VirtualDeviceManager; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; -import android.compat.annotation.EnabledSince; import android.content.ClipboardManager; import android.content.ContentCaptureOptions; import android.content.Context; @@ -172,8 +171,7 @@ import android.net.NetworkWatchlistManager; import android.net.PacProxyManager; import android.net.TetheringManager; import android.net.VpnManager; -import android.net.vcn.IVcnManagementService; -import android.net.vcn.VcnManager; +import android.net.vcn.VcnFrameworkInitializer; import android.net.wifi.WifiFrameworkInitializer; import android.net.wifi.nl80211.WifiNl80211Manager; import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager; @@ -208,7 +206,6 @@ import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.StatsFrameworkInitializer; import android.os.SystemConfigManager; -import android.os.SystemProperties; import android.os.SystemUpdateManager; import android.os.SystemVibrator; import android.os.SystemVibratorManager; @@ -235,8 +232,11 @@ import android.safetycenter.SafetyCenterFrameworkInitializer; import android.scheduling.SchedulingFrameworkInitializer; import android.security.FileIntegrityManager; import android.security.IFileIntegrityService; +import android.security.advancedprotection.AdvancedProtectionManager; +import android.security.advancedprotection.IAdvancedProtectionService; import android.security.attestationverification.AttestationVerificationManager; import android.security.attestationverification.IAttestationVerificationManagerService; +import android.security.keystore.KeyStoreManager; import android.service.oemlock.IOemLockService; import android.service.oemlock.OemLockManager; import android.service.persistentdata.IPersistentDataBlockService; @@ -299,18 +299,6 @@ public final class SystemServiceRegistry { /** @hide */ public static boolean sEnableServiceNotFoundWtf = false; - /** - * Starting with {@link VANILLA_ICE_CREAM}, Telephony feature flags - * (e.g. {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}) are being checked before - * returning managers that depend on them. If the feature is missing, - * {@link Context#getSystemService} will return null. - * - * This change is specific to VcnManager. - */ - @ChangeId - @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) - static final long ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN = 330902016; - /** * After {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, Wear devices will be allowed to publish * no {@link GameManager} instance. This is because the respective system service is no longer @@ -321,16 +309,6 @@ public final class SystemServiceRegistry { @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) static final long NULL_GAME_MANAGER_IN_WEAR = 340929737; - /** - * The corresponding vendor API for Android V - * - *

Starting with Android V, the vendor API format has switched to YYYYMM. - * - * @see Vendor API - * level - */ - private static final int VENDOR_API_FOR_ANDROID_V = 202404; - // Service registry information. // This information is never changed once static initialization has completed. private static final Map, String> SYSTEM_SERVICE_NAMES = @@ -497,22 +475,6 @@ public final class SystemServiceRegistry { return new VpnManager(ctx, service); }}); - registerService(Context.VCN_MANAGEMENT_SERVICE, VcnManager.class, - new CachedServiceFetcher() { - @Override - public VcnManager createService(ContextImpl ctx) throws ServiceNotFoundException { - final String telephonyFeatureToCheck = getVcnFeatureDependency(); - - if (telephonyFeatureToCheck != null - && !ctx.getPackageManager().hasSystemFeature(telephonyFeatureToCheck)) { - return null; - } - - IBinder b = ServiceManager.getService(Context.VCN_MANAGEMENT_SERVICE); - IVcnManagementService service = IVcnManagementService.Stub.asInterface(b); - return new VcnManager(ctx, service); - }}); - registerService(Context.COUNTRY_DETECTOR, CountryDetector.class, new StaticServiceFetcher() { @Override @@ -1744,6 +1706,17 @@ public final class SystemServiceRegistry { } }); + registerService(Context.KEYSTORE_SERVICE, KeyStoreManager.class, + new StaticServiceFetcher() { + @Override + public KeyStoreManager createService() + throws ServiceNotFoundException { + if (!android.security.Flags.keystoreGrantApi()) { + throw new ServiceNotFoundException("KeyStoreManager is not supported"); + } + return KeyStoreManager.getInstance(); + }}); + registerService(Context.CONTACT_KEYS_SERVICE, E2eeContactKeysManager.class, new CachedServiceFetcher() { @Override @@ -1771,6 +1744,21 @@ public final class SystemServiceRegistry { return new SupervisionManager(ctx, service); } }); + if (android.security.Flags.aapmApi()) { + registerService(Context.ADVANCED_PROTECTION_SERVICE, AdvancedProtectionManager.class, + new CachedServiceFetcher<>() { + @Override + public AdvancedProtectionManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + IBinder iBinder = ServiceManager.getServiceOrThrow( + Context.ADVANCED_PROTECTION_SERVICE); + IAdvancedProtectionService service = + IAdvancedProtectionService.Stub.asInterface(iBinder); + return new AdvancedProtectionManager(service); + } + }); + } + // DO NOT do a flag check like this unless the flag is read-only. // (because this code is executed during preload in zygote.) // If the flag is mutable, the check should be inside CachedServiceFetcher. @@ -1812,6 +1800,8 @@ public final class SystemServiceRegistry { OnDevicePersonalizationFrameworkInitializer.registerServiceWrappers(); DeviceLockFrameworkInitializer.registerServiceWrappers(); VirtualizationFrameworkInitializer.registerServiceWrappers(); + VcnFrameworkInitializer.registerServiceWrappers(); + if (com.android.server.telecom.flags.Flags.telecomMainlineBlockedNumbersManager()) { ProviderFrameworkInitializer.registerServiceWrappers(); } @@ -1873,30 +1863,6 @@ public final class SystemServiceRegistry { return manager.hasSystemFeature(featureName); } - // Suppressing AndroidFrameworkCompatChange because we're querying vendor - // partition SDK level, not application's target SDK version (which BTW we - // also check through Compatibility framework a few lines below). - @SuppressWarnings("AndroidFrameworkCompatChange") - @Nullable - private static String getVcnFeatureDependency() { - // Check SDK version of the client app. Apps targeting pre-V SDK might - // have not checked for existence of these features. - if (!Compatibility.isChangeEnabled(ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN)) { - return null; - } - - // Check SDK version of the vendor partition. Pre-V devices might have - // incorrectly under-declared telephony features. - final int vendorApiLevel = SystemProperties.getInt( - "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); - if (vendorApiLevel < VENDOR_API_FOR_ANDROID_V) { - return PackageManager.FEATURE_TELEPHONY; - } else { - return PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION; - } - - } - /** * Gets a system service from a given context. * @hide diff --git a/core/java/android/app/appfunctions/AppFunctionManager.java b/core/java/android/app/appfunctions/AppFunctionManager.java index 439d988e2588cd00e283174f7a6dee578a5134eb..dca433696fe744d679541c435cd8156f5a4de088 100644 --- a/core/java/android/app/appfunctions/AppFunctionManager.java +++ b/core/java/android/app/appfunctions/AppFunctionManager.java @@ -100,40 +100,6 @@ public final class AppFunctionManager { mContext = context; } - /** - * Executes the app function. - * - *

Note: Applications can execute functions they define. To execute functions defined in - * another component, apps would need to have {@code - * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@code - * android.permission.EXECUTE_APP_FUNCTIONS}. - * - * @param request the request to execute the app function - * @param executor the executor to run the callback - * @param callback the callback to receive the function execution result. if the calling app - * does not own the app function or does not have {@code - * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@code - * android.permission.EXECUTE_APP_FUNCTIONS}, the execution result will contain {@code - * ExecuteAppFunctionResponse.RESULT_DENIED}. - * @deprecated Use {@link #executeAppFunction(ExecuteAppFunctionRequest, Executor, - * CancellationSignal, Consumer)} instead. This method will be removed once usage references - * are updated. - */ - @RequiresPermission( - anyOf = { - Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED, - Manifest.permission.EXECUTE_APP_FUNCTIONS - }, - conditional = true) - @UserHandleAware - @Deprecated - public void executeAppFunction( - @NonNull ExecuteAppFunctionRequest request, - @NonNull @CallbackExecutor Executor executor, - @NonNull Consumer callback) { - executeAppFunction(request, executor, new CancellationSignal(), callback); - } - /** * Executes the app function. * diff --git a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java index 08ecced234a974d1a43b0df7bb8421934676caab..06d95f5270c38f67485db50adbdd4b394647a9bf 100644 --- a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java +++ b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java @@ -137,8 +137,10 @@ public class AppFunctionRuntimeMetadata extends GenericDocument { .TOKENIZER_TYPE_VERBATIM) .build()) .addProperty( - new AppSearchSchema.BooleanPropertyConfig.Builder(PROPERTY_ENABLED) + new AppSearchSchema.LongPropertyConfig.Builder(PROPERTY_ENABLED) .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL) + .setIndexingType( + AppSearchSchema.LongPropertyConfig.INDEXING_TYPE_RANGE) .build()) .addProperty( new AppSearchSchema.StringPropertyConfig.Builder( @@ -212,19 +214,14 @@ public class AppFunctionRuntimeMetadata extends GenericDocument { } /** - * Sets an indicator specifying if the function is enabled or not. This would override the - * default enabled state in the static metadata ({@link - * AppFunctionStaticMetadataHelper#STATIC_PROPERTY_ENABLED_BY_DEFAULT}). Sets this to null - * to clear the override. - * TODO(369683073) Replace the tristate Boolean with IntDef EnabledState. + * Sets an indicator specifying the function enabled state. */ @NonNull public Builder setEnabled(@EnabledState int enabledState) { if (enabledState != APP_FUNCTION_STATE_DEFAULT && enabledState != APP_FUNCTION_STATE_ENABLED && enabledState != APP_FUNCTION_STATE_DISABLED) { - throw new IllegalArgumentException( - "Value of EnabledState is unsupported."); + throw new IllegalArgumentException("Value of EnabledState is unsupported."); } setPropertyLong(PROPERTY_ENABLED, enabledState); return this; diff --git a/core/java/android/app/appfunctions/AppFunctionService.java b/core/java/android/app/appfunctions/AppFunctionService.java index ceca850a1037d3db9338556306ddf10a7fdba252..63d187aa11efe74d149fbae37e82a94e1d13439d 100644 --- a/core/java/android/app/appfunctions/AppFunctionService.java +++ b/core/java/android/app/appfunctions/AppFunctionService.java @@ -141,74 +141,6 @@ public abstract class AppFunctionService extends Service { return mBinder; } - /** - * Called by the system to execute a specific app function. - * - *

This method is triggered when the system requests your AppFunctionService to handle a - * particular function you have registered and made available. - * - *

To ensure proper routing of function requests, assign a unique identifier to each - * function. This identifier doesn't need to be globally unique, but it must be unique within - * your app. For example, a function to order food could be identified as "orderFood". In most - * cases this identifier should come from the ID automatically generated by the AppFunctions - * SDK. You can determine the specific function to invoke by calling {@link - * ExecuteAppFunctionRequest#getFunctionIdentifier()}. - * - *

This method is always triggered in the main thread. You should run heavy tasks on a worker - * thread and dispatch the result with the given callback. You should always report back the - * result using the callback, no matter if the execution was successful or not. - * - * @param request The function execution request. - * @param callback A callback to report back the result. - * @deprecated Use {@link #onExecuteFunction(ExecuteAppFunctionRequest, CancellationSignal, - * Consumer)} instead. This method will be removed once usage references are updated. - */ - @MainThread - @Deprecated - public void onExecuteFunction( - @NonNull ExecuteAppFunctionRequest request, - @NonNull Consumer callback) { - Log.w( - "AppFunctionService", - "Calling deprecated default implementation of onExecuteFunction"); - } - - /** - * Called by the system to execute a specific app function. - * - *

This method is triggered when the system requests your AppFunctionService to handle a - * particular function you have registered and made available. - * - *

To ensure proper routing of function requests, assign a unique identifier to each - * function. This identifier doesn't need to be globally unique, but it must be unique within - * your app. For example, a function to order food could be identified as "orderFood". In most - * cases this identifier should come from the ID automatically generated by the AppFunctions - * SDK. You can determine the specific function to invoke by calling {@link - * ExecuteAppFunctionRequest#getFunctionIdentifier()}. - * - *

This method is always triggered in the main thread. You should run heavy tasks on a worker - * thread and dispatch the result with the given callback. You should always report back the - * result using the callback, no matter if the execution was successful or not. - * - *

This method also accepts a {@link CancellationSignal} that the app should listen to cancel - * the execution of function if requested by the system. - * - * @param request The function execution request. - * @param cancellationSignal A signal to cancel the execution. - * @param callback A callback to report back the result. - * @deprecated Use {@link #onExecuteFunction(ExecuteAppFunctionRequest, String, - * CancellationSignal, Consumer)} instead. This method will be removed once usage references - * are updated. - */ - @MainThread - @Deprecated - public void onExecuteFunction( - @NonNull ExecuteAppFunctionRequest request, - @NonNull CancellationSignal cancellationSignal, - @NonNull Consumer callback) { - onExecuteFunction(request, callback); - } - /** * Called by the system to execute a specific app function. * @@ -235,11 +167,9 @@ public abstract class AppFunctionService extends Service { * @param callback A callback to report back the result. */ @MainThread - public void onExecuteFunction( + public abstract void onExecuteFunction( @NonNull ExecuteAppFunctionRequest request, @NonNull String callingPackage, @NonNull CancellationSignal cancellationSignal, - @NonNull Consumer callback) { - onExecuteFunction(request, cancellationSignal, callback); - } + @NonNull Consumer callback); } diff --git a/core/java/android/app/contextualsearch/ContextualSearchManager.java b/core/java/android/app/contextualsearch/ContextualSearchManager.java index cfbe7416bf9df7ae15548feae7516b2db5a0ba8b..3438cc8616614281c89f9d3d70d89921dcf8b86e 100644 --- a/core/java/android/app/contextualsearch/ContextualSearchManager.java +++ b/core/java/android/app/contextualsearch/ContextualSearchManager.java @@ -102,6 +102,7 @@ public final class ContextualSearchManager { * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH. */ public static final String EXTRA_TOKEN = "android.app.contextualsearch.extra.TOKEN"; + /** * Intent action for contextual search invocation. The app providing the contextual search * experience must add this intent filter action to the activity it wants to be launched. @@ -111,6 +112,14 @@ public final class ContextualSearchManager { public static final String ACTION_LAUNCH_CONTEXTUAL_SEARCH = "android.app.contextualsearch.action.LAUNCH_CONTEXTUAL_SEARCH"; + /** + * System feature declaring that the device supports Contextual Search. + * + * @hide + */ + public static final String FEATURE_CONTEXTUAL_SEARCH = + "com.google.android.feature.CONTEXTUAL_SEARCH"; + /** Entrypoint to be used when a user long presses on the nav handle. */ public static final int ENTRYPOINT_LONG_PRESS_NAV_HANDLE = 1; /** Entrypoint to be used when a user long presses on the home button. */ diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig index 8014537e8838bce751febfeecacc4b2f799edbb0..37fa9a26b91cbf57c61fe9748674a4944709992b 100644 --- a/core/java/android/app/notification.aconfig +++ b/core/java/android/app/notification.aconfig @@ -5,6 +5,14 @@ container: "system" # when appropriate, as it's not currently part of the namespace so it may not be obvious what the # flag relates to. +flag { + name: "notifications_redesign_app_icons" + namespace: "systemui" + description: "Notifications Redesign: Use app icons in notification rows (not to be confused with" + " notifications_use_app_icons, notifications_use_app_icon_in_row which are just experiments)." + bug: "371174789" +} + flag { name: "modes_api" is_exported: true @@ -47,6 +55,16 @@ flag { bug: "360862012" } +flag { + name: "modes_hsum" + namespace: "systemui" + description: "Fixes for modes (and DND/Zen in general) with HSUM or secondary users" + bug: "366203070" + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { name: "api_tvextender" is_exported: true @@ -262,3 +280,10 @@ flag { description: "[RONs] Guards new promotion logic and UI, including AOD notification and Colorization" bug: "367705002" } + +flag { + name: "backup_restore_logging" + namespace: "systemui" + description: "Adds logging for notification/modes backup and restore events" + bug: "289524803" +} \ No newline at end of file diff --git a/core/java/android/app/usage/UsageEventsQuery.java b/core/java/android/app/usage/UsageEventsQuery.java index c0f13ca557e241a96126545297e3c94e9d0935d3..ecf4cd115fefdb25d7374844ad16558fad5d0ea1 100644 --- a/core/java/android/app/usage/UsageEventsQuery.java +++ b/core/java/android/app/usage/UsageEventsQuery.java @@ -75,7 +75,7 @@ public final class UsageEventsQuery implements Parcelable { } /** - * Returns the exclusive timpstamp to indicate the end of the range of events. + * Returns the exclusive timestamp to indicate the end of the range of events. * Defined in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}. */ public @CurrentTimeMillisLong long getEndTimeMillis() { diff --git a/core/java/android/companion/AssociationInfo.java b/core/java/android/companion/AssociationInfo.java index 7f30d7cccb57b25f4f687b387228d921985e3915..124973489dd197f7b4abb16702022e6fb2badd65 100644 --- a/core/java/android/companion/AssociationInfo.java +++ b/core/java/android/companion/AssociationInfo.java @@ -287,7 +287,7 @@ public final class AssociationInfo implements Parcelable { /** * Get the device icon of the associated device. The device icon represents the device type. * - * @return the device icon, or {@code null} if no device icon is has been set for the + * @return the device icon, or {@code null} if no device icon has been set for the * associated device. * * @see AssociationRequest.Builder#setDeviceIcon(Icon) diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java index 41a6791d8a7bb054d0c8c5f1dbadd7128c22fb47..f368935a74c8ab6925a029b1333d4dd93990b9ed 100644 --- a/core/java/android/companion/AssociationRequest.java +++ b/core/java/android/companion/AssociationRequest.java @@ -475,8 +475,8 @@ public final class AssociationRequest implements Parcelable { } /** - * Set the device icon for the self-managed device and this icon will be - * displayed in the self-managed association dialog. + * Set the device icon for the self-managed device and to display the icon in the + * self-managed association dialog. * * @throws IllegalArgumentException if the icon is not exactly 24dp by 24dp * or if it is {@link Icon#TYPE_URI} or {@link Icon#TYPE_URI_ADAPTIVE_BITMAP}. diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index dfad6de4ba167a8b6c9af1ee2a62d2de97547038..4472c3d13d7c7cb0b4ddd609301cd3d23acd9a79 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -478,6 +478,15 @@ public final class CompanionDeviceManager { Objects.requireNonNull(callback, "Callback cannot be null"); handler = Handler.mainIfNull(handler); + if (Flags.associationDeviceIcon()) { + final Icon deviceIcon = request.getDeviceIcon(); + + if (deviceIcon != null && !isValidIcon(deviceIcon, mContext)) { + throw new IllegalArgumentException("The size of the device icon must be " + + "24dp x 24dp to ensure proper display"); + } + } + try { mService.associate(request, new AssociationRequestCallbackProxy(handler, callback), mContext.getOpPackageName(), mContext.getUserId()); @@ -542,11 +551,13 @@ public final class CompanionDeviceManager { Objects.requireNonNull(executor, "Executor cannot be null"); Objects.requireNonNull(callback, "Callback cannot be null"); - final Icon deviceIcon = request.getDeviceIcon(); + if (Flags.associationDeviceIcon()) { + final Icon deviceIcon = request.getDeviceIcon(); - if (deviceIcon != null && !isValidIcon(deviceIcon, mContext)) { - throw new IllegalArgumentException("The size of the device icon must be 24dp x 24dp to" - + "ensure proper display"); + if (deviceIcon != null && !isValidIcon(deviceIcon, mContext)) { + throw new IllegalArgumentException("The size of the device icon must be " + + "24dp x 24dp to ensure proper display"); + } } try { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 91f7a8bae16358549601640b5228f3251fd7eff7..07106e8359d400d2346d7a5edd75024d67b3d3e9 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4325,6 +4325,7 @@ public abstract class Context { //@hide: ECM_ENHANCED_CONFIRMATION_SERVICE, CONTACT_KEYS_SERVICE, RANGING_SERVICE, + ADVANCED_PROTECTION_SERVICE, }) @Retention(RetentionPolicy.SOURCE) @@ -4767,6 +4768,18 @@ public abstract class Context { */ public static final String SENSOR_PRIVACY_SERVICE = "sensor_privacy"; + /** + * Use with {@link #getSystemService(String)} to retrieve a {@link + * android.security.keystore.KeyStoreManager} for accessing + * Android Keystore + * functions. + * + * @see #getSystemService(String) + * @see android.security.keystore.KeyStoreManager + */ + @FlaggedApi(android.security.Flags.FLAG_KEYSTORE_GRANT_API) + public static final String KEYSTORE_SERVICE = "keystore"; + /** * Use with {@link #getSystemService(String)} to retrieve a {@link * android.os.storage.StorageManager} for accessing system storage @@ -5657,6 +5670,14 @@ public abstract class Context { @SuppressLint("ServiceName") public static final String BINARY_TRANSPARENCY_SERVICE = "transparency"; + /** + * System service name for ForensicService. + * The service manages the forensic info on device. + * @hide + */ + @FlaggedApi(android.security.Flags.FLAG_AFL_API) + public static final String FORENSIC_SERVICE = "forensic"; + /** * System service name for the DeviceIdleManager. * @see #getSystemService(String) @@ -6366,6 +6387,15 @@ public abstract class Context { */ public static final String ATTESTATION_VERIFICATION_SERVICE = "attestation_verification"; + /** + * Use with {@link #getSystemService(String)} to retrieve an + * {@link android.security.advancedprotection.AdvancedProtectionManager} + * @see #getSystemService(String) + * @see android.security.advancedprotection.AdvancedProtectionManager + */ + @FlaggedApi(android.security.Flags.FLAG_AAPM_API) + public static final String ADVANCED_PROTECTION_SERVICE = "advanced_protection"; + /** * Use with {@link #getSystemService(String)} to retrieve an * {@link android.security.FileIntegrityManager}. diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 0bb0027fb0c3463c5aa66d283decfc375a39fc45..f7195284987226a9b48b00e06f87dbe2bc9b761f 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -888,6 +888,22 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_ACTIVITY_RECOGNIZER = "android.intent.action.ACTIVITY_RECOGNIZER"; + /** @hide */ + public static void maybeMarkAsMissingCreatorToken(Object object) { + if (object instanceof Intent intent) { + maybeMarkAsMissingCreatorTokenInternal(intent); + } + } + + private static void maybeMarkAsMissingCreatorTokenInternal(Intent intent) { + boolean isForeign = (intent.mLocalFlags & LOCAL_FLAG_FROM_PARCEL) != 0; + boolean isWithoutTrustedCreatorToken = + (intent.mLocalFlags & Intent.LOCAL_FLAG_TRUSTED_CREATOR_TOKEN_PRESENT) == 0; + if (isForeign && isWithoutTrustedCreatorToken) { + intent.addExtendedFlags(EXTENDED_FLAG_MISSING_CREATOR_OR_INVALID_TOKEN); + } + } + /** * Represents a shortcut/live folder icon resource. * @@ -7684,10 +7700,8 @@ public class Intent implements Parcelable, Cloneable { /** * This flag indicates the creator token of this intent has been verified. - * - * @hide */ - public static final int LOCAL_FLAG_CREATOR_TOKEN_VERIFIED = 1 << 6; + private static final int LOCAL_FLAG_TRUSTED_CREATOR_TOKEN_PRESENT = 1 << 6; /** @hide */ @IntDef(flag = true, prefix = { "EXTENDED_FLAG_" }, value = { @@ -12243,6 +12257,30 @@ public class Intent implements Parcelable, Cloneable { } } + /** @hide */ + public void checkCreatorToken() { + if (mExtras == null) return; + if (mCreatorTokenInfo != null && mCreatorTokenInfo.mExtraIntentKeys != null) { + for (String key : mCreatorTokenInfo.mExtraIntentKeys) { + try { + Intent extraIntent = mExtras.getParcelable(key, Intent.class); + if (extraIntent == null) { + Log.w(TAG, "The key {" + key + + "} does not correspond to an intent in the bundle."); + continue; + } + extraIntent.mLocalFlags |= LOCAL_FLAG_TRUSTED_CREATOR_TOKEN_PRESENT; + } catch (Exception e) { + Log.e(TAG, "Failed to validate creator token. key: " + key + ".", e); + } + } + } + // mark the bundle as intent extras after calls to getParcelable. + // otherwise, the logic to mark missing token would run before + // mark trusted creator token present. + mExtras.setIsIntentExtra(); + } + public void writeToParcel(Parcel out, int flags) { out.writeString8(mAction); Uri.writeToParcel(out, mData); @@ -12730,6 +12768,7 @@ public class Intent implements Parcelable, Cloneable { } mLocalFlags |= localFlags; + checkCreatorToken(); // Special attribution fix-up logic for any BluetoothDevice extras // passed via Bluetooth intents diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS index 6d9dc456f38d706ab54ef84c8f8ded8487aa0075..392f62a8730268727d43bf467d70e43aa08c7ebf 100644 --- a/core/java/android/content/OWNERS +++ b/core/java/android/content/OWNERS @@ -1,11 +1,11 @@ # Remain no owner because multiple modules may touch this file. per-file Context.java = * per-file ContextWrapper.java = * -per-file *Content* = file:/services/core/java/com/android/server/am/OWNERS -per-file *Sync* = file:/services/core/java/com/android/server/am/OWNERS +per-file *Content* = varunshah@google.com, yamasani@google.com +per-file *Sync* = file:/apex/jobscheduler/JOB_OWNERS per-file IntentFilter.java = file:/PACKAGE_MANAGER_OWNERS per-file UriRelativeFilter* = file:/PACKAGE_MANAGER_OWNERS -per-file IntentFilter.java = file:/services/core/java/com/android/server/am/OWNERS +per-file IntentFilter.java = file:/INTENT_OWNERS per-file Intent.java = file:/INTENT_OWNERS per-file AutofillOptions* = file:/core/java/android/service/autofill/OWNERS per-file ContentCaptureOptions* = file:/core/java/android/service/contentcapture/OWNERS diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 481e6b5301620037df0ec1c89a1e530c00c1d605..ce52825ddb7377896d9a0c9ecff05510b0b2462f 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -21,10 +21,12 @@ import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.TestApi; import android.app.Activity; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.EnabledSince; import android.compat.annotation.Overridable; import android.compat.annotation.UnsupportedAppUsage; @@ -1203,6 +1205,18 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface SizeChangesSupportMode {} + /** + * This change id makes the restriction of fixed orientation, aspect ratio, and resizability + * of the app to be ignored, which means making the app fill the given available area. + * @hide + */ + @ChangeId + @Overridable + @TestApi + @SuppressLint("UnflaggedApi") // @TestApi without associated public API. + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) + public static final long UNIVERSAL_RESIZABLE_BY_DEFAULT = 357141415L; // buganizer id + /** * This change id enables compat policy that ignores app requested orientation in * response to an app calling {@link android.app.Activity#setRequestedOrientation}. See diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl index 451c0e5e079ad0c7314c7421e61a6be182831703..c911326ccffd2af794cea3385e126783b6fb1d00 100644 --- a/core/java/android/content/pm/IPackageInstaller.aidl +++ b/core/java/android/content/pm/IPackageInstaller.aidl @@ -93,4 +93,10 @@ interface IPackageInstaller { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES,android.Manifest.permission.REQUEST_INSTALL_PACKAGES})") void reportUnarchivalStatus(int unarchiveId, int status, long requiredStorageBytes, in PendingIntent userActionIntent, in UserHandle userHandle); + + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") + int getVerificationPolicy(); + + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") + boolean setVerificationPolicy(int policy); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index c673d5846d5dea82ed0d104eeb982f3f0b3b1a84..5da1444ac1db440d12261ca8814884b4452bcdde 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -62,6 +62,8 @@ import android.content.pm.parsing.PackageLite; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; import android.content.pm.verify.domain.DomainSet; +import android.content.pm.verify.pkg.VerificationSession; +import android.content.pm.verify.pkg.VerificationStatus; import android.graphics.Bitmap; import android.icu.util.ULocale; import android.net.Uri; @@ -417,6 +419,21 @@ public class PackageInstaller { */ public static final String EXTRA_WARNINGS = "android.content.pm.extra.WARNINGS"; + /** + * When verification is blocked as part of the installation, additional reason for the block + * will be provided to the installer with a {@link VerificationFailedReason} as part of the + * installation result returned via the {@link IntentSender} in + * {@link Session#commit(IntentSender)}. This extra is provided only when the installation has + * failed. Installers can use this extra to check if the installation failure was caused by a + * verification failure. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final String EXTRA_VERIFICATION_FAILURE_REASON = + "android.content.pm.extra.VERIFICATION_FAILURE_REASON"; + /** * Streaming installation pending. * Caller should make sure DataLoader is able to prepare image and reinitiate the operation. @@ -760,6 +777,90 @@ public class PackageInstaller { @Retention(RetentionPolicy.SOURCE) public @interface UnarchivalStatus {} + /** + * Verification failed because of unknown reasons, such as when the verifier times out or cannot + * be connected. It can also corresponds to the status of + * {@link VerificationSession#VERIFICATION_INCOMPLETE_UNKNOWN} reported by the verifier via + * {@link VerificationSession#reportVerificationIncomplete(int)}. + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final int VERIFICATION_FAILED_REASON_UNKNOWN = 0; + + /** + * Verification failed because the network is unavailable. This corresponds to the status of + * {@link VerificationSession#VERIFICATION_INCOMPLETE_NETWORK_UNAVAILABLE} reported by the + * verifier via {@link VerificationSession#reportVerificationIncomplete(int)}. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final int VERIFICATION_FAILED_REASON_NETWORK_UNAVAILABLE = 1; + + /** + * Verification failed because the package is blocked, as reported by the verifier via + * {@link VerificationSession#reportVerificationComplete(VerificationStatus)} or + * {@link VerificationSession#reportVerificationComplete(VerificationStatus, PersistableBundle)} + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final int VERIFICATION_FAILED_REASON_PACKAGE_BLOCKED = 2; + + /** + * @hide + */ + @IntDef(value = { + VERIFICATION_FAILED_REASON_UNKNOWN, + VERIFICATION_FAILED_REASON_NETWORK_UNAVAILABLE, + VERIFICATION_FAILED_REASON_PACKAGE_BLOCKED, + }) + public @interface VerificationFailedReason { + } + + /** + * Do not block installs, regardless of verification status. + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final int VERIFICATION_POLICY_NONE = 0; // platform default + /** + * Only block installations on {@link #VERIFICATION_FAILED_REASON_PACKAGE_BLOCKED}. + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final int VERIFICATION_POLICY_BLOCK_FAIL_OPEN = 1; + /** + * Only block installations on {@link #VERIFICATION_FAILED_REASON_PACKAGE_BLOCKED} and ask the + * user if they'd like to install anyway when the verification is blocked for other reason. + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final int VERIFICATION_POLICY_BLOCK_FAIL_WARN = 2; + /** + * Block installations whose verification status is blocked for any reason. + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + public static final int VERIFICATION_POLICY_BLOCK_FAIL_CLOSED = 3; + /** + * @hide + */ + @IntDef(value = { + VERIFICATION_POLICY_NONE, + VERIFICATION_POLICY_BLOCK_FAIL_OPEN, + VERIFICATION_POLICY_BLOCK_FAIL_WARN, + VERIFICATION_POLICY_BLOCK_FAIL_CLOSED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface VerificationPolicy { + } /** Default set of checksums - includes all available checksums. * @see Session#requestChecksums */ @@ -1502,6 +1603,40 @@ public class PackageInstaller { } } + /** + * Return the current verification enforcement policy. This may only be called by the + * package currently set by the system as the verifier agent. + * @hide + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) + public final @VerificationPolicy int getVerificationPolicy() { + try { + return mInstaller.getVerificationPolicy(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set the current verification enforcement policy which will be applied to all the future + * installation sessions. This may only be called by the package currently set by the system as + * the verifier agent. + * @hide + * @return whether the new policy was successfully set. + */ + @FlaggedApi(Flags.FLAG_VERIFICATION_SERVICE) + @SystemApi + @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) + public final boolean setVerificationPolicy(@VerificationPolicy int policy) { + try { + return mInstaller.setVerificationPolicy(policy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * An installation that is being actively staged. For an install to succeed, * all existing and new packages must have identical package names, version @@ -2799,6 +2934,8 @@ public class PackageInstaller { public int unarchiveId = -1; /** {@hide} */ public @Nullable String dexoptCompilerFilter = null; + /** {@hide} */ + public boolean forceVerification; private final ArrayMap mPermissionStates; @@ -2853,6 +2990,7 @@ public class PackageInstaller { developmentInstallFlags = source.readInt(); unarchiveId = source.readInt(); dexoptCompilerFilter = source.readString(); + forceVerification = source.readBoolean(); } /** {@hide} */ @@ -2889,6 +3027,7 @@ public class PackageInstaller { ret.developmentInstallFlags = developmentInstallFlags; ret.unarchiveId = unarchiveId; ret.dexoptCompilerFilter = dexoptCompilerFilter; + ret.forceVerification = forceVerification; return ret; } @@ -3597,6 +3736,14 @@ public class PackageInstaller { return grantedPermissions.toArray(ArrayUtils.emptyArray(String.class)); } + /** + * Used by adb installations to force enable the verification for this install. + * {@hide} + */ + public void setForceVerification() { + this.forceVerification = true; + } + /** {@hide} */ public void dump(IndentingPrintWriter pw) { pw.printPair("mode", mode); @@ -3632,6 +3779,7 @@ public class PackageInstaller { pw.printHexPair("developmentInstallFlags", developmentInstallFlags); pw.printPair("unarchiveId", unarchiveId); pw.printPair("dexoptCompilerFilter", dexoptCompilerFilter); + pw.printPair("forceVerification", forceVerification); pw.println(); } @@ -3678,6 +3826,7 @@ public class PackageInstaller { dest.writeInt(developmentInstallFlags); dest.writeInt(unarchiveId); dest.writeString(dexoptCompilerFilter); + dest.writeBoolean(forceVerification); } public static final Parcelable.Creator diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index c7d7dc1eb0dedb2c143118032c6ca4ed3ea3e00c..5b38942d468d97d5b0da12f2ca9be665319f2a82 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -326,3 +326,19 @@ flag { bug: "360129103" is_fixed_read_only: true } + +flag { + name: "include_feature_flags_in_package_cacher" + namespace: "package_manager_service" + description: "Include feature flag status when determining hits or misses in PackageCacher." + bug: "364771256" + is_fixed_read_only: true +} + +flag { + name: "reduce_broadcasts_for_component_state_changes" + namespace: "package_manager_service" + description: "Feature flag to limit sending of the PACKAGE_CHANGED broadcast to only the system and the application itself during component state changes." + bug: "292261144" + is_fixed_read_only: true +} diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 7de7131fc2ad86b2c97c1a24c1b7f14cc189f9c8..35f9cff1aedb9a8bd7e2ac8dddfedf223832904e 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -210,6 +210,18 @@ flag { } } +flag { + name: "property_invalidated_cache_bypass_mismatched_uids" + namespace: "multiuser" + description: "Bypass the cache when the process UID does not match the binder UID." + bug: "373752556" + metadata { + purpose: PURPOSE_BUGFIX + } + is_fixed_read_only: true +} + + flag { name: "cache_profile_parent_read_only" namespace: "multiuser" @@ -521,3 +533,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "ignore_restrictions_when_deleting_private_profile" + namespace: "multiuser" + description: "Ignore any user restrictions when deleting private profiles." + bug: "350953833" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/core/java/android/content/pm/verify/pkg/IVerificationSessionCallback.aidl b/core/java/android/content/pm/verify/pkg/IVerificationSessionCallback.aidl deleted file mode 100644 index 38a7956603aeab59e275968eebe26a83ecc5b31d..0000000000000000000000000000000000000000 --- a/core/java/android/content/pm/verify/pkg/IVerificationSessionCallback.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.pm.verify.pkg; - -import android.content.pm.verify.pkg.VerificationStatus; -import android.os.PersistableBundle; - -/** - * Oneway interface that allows the verifier to send response or verification results back to - * the system. - * @hide - */ -oneway interface IVerificationSessionCallback { - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") - void reportVerificationIncomplete(int verificationId, int reason); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") - void reportVerificationComplete(int verificationId, in VerificationStatus status); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") - void reportVerificationCompleteWithExtensionResponse(int verificationId, in VerificationStatus status, in PersistableBundle response); -} diff --git a/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl b/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl index 7a9484abd1b1b7475e4072116464f84a54340f11..66caf2d0fec0c90f46c97e4a83cd13187c2676f0 100644 --- a/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl +++ b/core/java/android/content/pm/verify/pkg/IVerificationSessionInterface.aidl @@ -16,8 +16,11 @@ package android.content.pm.verify.pkg; +import android.content.pm.verify.pkg.VerificationStatus; +import android.os.PersistableBundle; + /** - * Non-oneway interface that allows the verifier to retrieve information from the system. + * Non-oneway interface that allows the verifier to communicate with the system. * @hide */ interface IVerificationSessionInterface { @@ -25,4 +28,12 @@ interface IVerificationSessionInterface { long getTimeoutTime(int verificationId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") long extendTimeRemaining(int verificationId, long additionalMs); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") + boolean setVerificationPolicy(int verificationId, int policy); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") + void reportVerificationIncomplete(int verificationId, int reason); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") + void reportVerificationComplete(int verificationId, in VerificationStatus status); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT)") + void reportVerificationCompleteWithExtensionResponse(int verificationId, in VerificationStatus status, in PersistableBundle response); } \ No newline at end of file diff --git a/core/java/android/content/pm/verify/pkg/VerificationSession.java b/core/java/android/content/pm/verify/pkg/VerificationSession.java index 70b4a022f52164bb73e452a58b2e6faf89aaf4a0..4ade21198f37425d38376bf4a7f7b0d557e5329c 100644 --- a/core/java/android/content/pm/verify/pkg/VerificationSession.java +++ b/core/java/android/content/pm/verify/pkg/VerificationSession.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.pm.Flags; +import android.content.pm.PackageInstaller; import android.content.pm.SharedLibraryInfo; import android.content.pm.SigningInfo; import android.net.Uri; @@ -52,17 +53,12 @@ public final class VerificationSession implements Parcelable { * The verification cannot be completed because the network is unavailable. */ public static final int VERIFICATION_INCOMPLETE_NETWORK_UNAVAILABLE = 1; - /** - * The verification cannot be completed because the network is limited. - */ - public static final int VERIFICATION_INCOMPLETE_NETWORK_LIMITED = 2; /** * @hide */ @IntDef(prefix = {"VERIFICATION_INCOMPLETE_"}, value = { VERIFICATION_INCOMPLETE_NETWORK_UNAVAILABLE, - VERIFICATION_INCOMPLETE_NETWORK_LIMITED, VERIFICATION_INCOMPLETE_UNKNOWN, }) @Retention(RetentionPolicy.SOURCE) @@ -83,8 +79,15 @@ public final class VerificationSession implements Parcelable { private final PersistableBundle mExtensionParams; @NonNull private final IVerificationSessionInterface mSession; - @NonNull - private final IVerificationSessionCallback mCallback; + /** + * The current policy that is active for the session. It might not be + * the same as the original policy that was initially assigned for this verification session, + * because the active policy can be overridden by {@link #setVerificationPolicy(int)}. + *

To improve the latency, store the original policy value and any changes made to it, + * so that {@link #getVerificationPolicy()} does not need to make a binder call to retrieve the + * currently active policy.

+ */ + private volatile @PackageInstaller.VerificationPolicy int mVerificationPolicy; /** * Constructor used by the system to describe the details of a verification session. @@ -94,8 +97,8 @@ public final class VerificationSession implements Parcelable { @NonNull Uri stagedPackageUri, @NonNull SigningInfo signingInfo, @NonNull List declaredLibraries, @NonNull PersistableBundle extensionParams, - @NonNull IVerificationSessionInterface session, - @NonNull IVerificationSessionCallback callback) { + @PackageInstaller.VerificationPolicy int defaultPolicy, + @NonNull IVerificationSessionInterface session) { mId = id; mInstallSessionId = installSessionId; mPackageName = packageName; @@ -103,8 +106,8 @@ public final class VerificationSession implements Parcelable { mSigningInfo = signingInfo; mDeclaredLibraries = declaredLibraries; mExtensionParams = extensionParams; + mVerificationPolicy = defaultPolicy; mSession = session; - mCallback = callback; } /** @@ -144,7 +147,7 @@ public final class VerificationSession implements Parcelable { /** * Returns a mapping of any shared libraries declared in the manifest - * to the {@link SharedLibraryInfo#Type} that is declared. This will be an empty + * to the {@link SharedLibraryInfo.Type} that is declared. This will be an empty * map if no shared libraries are declared by the package. */ @NonNull @@ -173,6 +176,39 @@ public final class VerificationSession implements Parcelable { } } + /** + * Return the current policy that is active for this session. + *

If the policy for this session has been changed by {@link #setVerificationPolicy}, + * the return value of this method is the current policy that is active for this session. + * Otherwise, the return value is the same as the initial policy that was assigned to the + * session when it was first created.

+ */ + public @PackageInstaller.VerificationPolicy int getVerificationPolicy() { + return mVerificationPolicy; + } + + /** + * Override the verification policy for this session. + * @return True if the override was successful, False otherwise. + */ + @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) + public boolean setVerificationPolicy(@PackageInstaller.VerificationPolicy int policy) { + if (mVerificationPolicy == policy) { + // No effective policy change + return true; + } + try { + if (mSession.setVerificationPolicy(mId, policy)) { + mVerificationPolicy = policy; + return true; + } else { + return false; + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Extend the timeout for this session by the provided additionalMs to * fetch relevant information over the network or wait for the network. @@ -196,7 +232,7 @@ public final class VerificationSession implements Parcelable { @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationIncomplete(@VerificationIncompleteReason int reason) { try { - mCallback.reportVerificationIncomplete(mId, reason); + mSession.reportVerificationIncomplete(mId, reason); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -210,7 +246,7 @@ public final class VerificationSession implements Parcelable { @RequiresPermission(android.Manifest.permission.VERIFICATION_AGENT) public void reportVerificationComplete(@NonNull VerificationStatus status) { try { - mCallback.reportVerificationComplete(mId, status); + mSession.reportVerificationComplete(mId, status); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -225,7 +261,7 @@ public final class VerificationSession implements Parcelable { public void reportVerificationComplete(@NonNull VerificationStatus status, @NonNull PersistableBundle response) { try { - mCallback.reportVerificationCompleteWithExtensionResponse(mId, status, response); + mSession.reportVerificationCompleteWithExtensionResponse(mId, status, response); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -239,8 +275,8 @@ public final class VerificationSession implements Parcelable { mSigningInfo = SigningInfo.CREATOR.createFromParcel(in); mDeclaredLibraries = in.createTypedArrayList(SharedLibraryInfo.CREATOR); mExtensionParams = in.readPersistableBundle(getClass().getClassLoader()); + mVerificationPolicy = in.readInt(); mSession = IVerificationSessionInterface.Stub.asInterface(in.readStrongBinder()); - mCallback = IVerificationSessionCallback.Stub.asInterface(in.readStrongBinder()); } @Override @@ -257,8 +293,8 @@ public final class VerificationSession implements Parcelable { mSigningInfo.writeToParcel(dest, flags); dest.writeTypedList(mDeclaredLibraries); dest.writePersistableBundle(mExtensionParams); + dest.writeInt(mVerificationPolicy); dest.writeStrongBinder(mSession.asBinder()); - dest.writeStrongBinder(mCallback.asBinder()); } @NonNull diff --git a/core/java/android/content/pm/xr.aconfig b/core/java/android/content/pm/xr.aconfig new file mode 100644 index 0000000000000000000000000000000000000000..61835c162c498112dd28200c7843aafeac2898d2 --- /dev/null +++ b/core/java/android/content/pm/xr.aconfig @@ -0,0 +1,9 @@ +package: "android.xr" +container: "system" + +flag { + namespace: "xr" + name: "xr_manifest_entries" + description: "Adds manifest entries used by Android XR" + bug: "364416355" +} \ No newline at end of file diff --git a/core/java/android/hardware/DataSpace.java b/core/java/android/hardware/DataSpace.java index 312bfdf777d60bf167e0a86facb66ec028e18ec9..611738435f7ed5f0b33b77b2b8338113ddf097cf 100644 --- a/core/java/android/hardware/DataSpace.java +++ b/core/java/android/hardware/DataSpace.java @@ -15,9 +15,12 @@ */ package android.hardware; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.view.SurfaceControl; +import com.android.graphics.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -639,6 +642,18 @@ public final class DataSpace { */ public static final int DATASPACE_SRGB_LINEAR = 138477568; + /** + * Display BT. 2020 encoding. + * + *

Composed of the following -

+ *
+     *   Primaries: STANDARD_BT2020
+     *   Transfer: TRANSFER_SRGB
+     *   Range: RANGE_FULL
+ */ + @FlaggedApi(Flags.FLAG_DISPLAY_BT2020_COLORSPACE) + public static final int DATASPACE_DISPLAY_BT2020 = 142999552; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { @@ -660,7 +675,8 @@ public final class DataSpace { DATASPACE_BT2020, DATASPACE_BT709, DATASPACE_DCI_P3, - DATASPACE_SRGB_LINEAR + DATASPACE_SRGB_LINEAR, + DATASPACE_DISPLAY_BT2020 }) public @interface NamedDataSpace {}; diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java index 8c87ad3353b6480e09503c22b8b04a94fa5591b7..93958443c01bc1289e60f5a0ee62de7235d8ea9b 100644 --- a/core/java/android/hardware/HardwareBuffer.java +++ b/core/java/android/hardware/HardwareBuffer.java @@ -283,7 +283,7 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable { private static NativeAllocationRegistry getRegistry(long size) { final long func = nGetNativeFinalizer(); final Class cls = HardwareBuffer.class; - return com.android.libcore.Flags.nativeMetrics() + return com.android.libcore.readonly.Flags.nativeMetrics() ? NativeAllocationRegistry.createNonmalloced(cls, func, size) : NativeAllocationRegistry.createNonmalloced(cls.getClassLoader(), func, size); } diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 97f6899ff1411547b1f13e49120bc56807e1194e..b0ea92d140a50997ed853f9a1debf0aab141d2fe 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -18,6 +18,7 @@ package android.hardware.display; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.HdrCapabilities.HdrType; +import static android.view.Display.INVALID_DISPLAY; import android.Manifest; import android.annotation.FlaggedApi; @@ -47,6 +48,7 @@ import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserManager; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -96,6 +98,8 @@ public final class DisplayManager { @GuardedBy("mLock") private final WeakDisplayCache mDisplayCache = new WeakDisplayCache(); + private int mDisplayIdToMirror = INVALID_DISPLAY; + /** * Broadcast receiver that indicates when the Wifi display status changes. *

@@ -1086,6 +1090,7 @@ public final class DisplayManager { if (surface != null) { builder.setSurface(surface); } + builder.setDisplayIdToMirror(getDisplayIdToMirror()); return createVirtualDisplay(builder.build(), handler, callback); } @@ -1163,6 +1168,7 @@ public final class DisplayManager { if (surface != null) { builder.setSurface(surface); } + builder.setDisplayIdToMirror(getDisplayIdToMirror()); return createVirtualDisplay(projection, builder.build(), callback, handler); } @@ -1708,6 +1714,16 @@ public final class DisplayManager { return mGlobal.getDefaultDozeBrightness(displayId); } + private int getDisplayIdToMirror() { + if (mDisplayIdToMirror == INVALID_DISPLAY) { + final UserManager userManager = mContext.getSystemService(UserManager.class); + mDisplayIdToMirror = userManager.isVisibleBackgroundUsersSupported() + ? userManager.getMainDisplayIdAssignedToUser() + : DEFAULT_DISPLAY; + } + return mDisplayIdToMirror; + } + /** * Listens for changes in available display devices. */ diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig index 99eeca98bce02005aa34ef3aec820842ed8d6c2a..66697546a24ac57788d0f8fae401a1a0c4727ab3 100644 --- a/core/java/android/hardware/input/input_framework.aconfig +++ b/core/java/android/hardware/input/input_framework.aconfig @@ -25,14 +25,6 @@ flag { bug: "294546335" } -flag { - namespace: "input_native" - name: "pointer_coords_is_resampled_api" - is_exported: true - description: "Makes MotionEvent.PointerCoords#isResampled() a public API" - bug: "298197511" -} - flag { namespace: "input_native" name: "emoji_and_screenshot_keycodes_available" @@ -142,3 +134,10 @@ flag { description: "Controls whether the connected mice's primary buttons, left and right, can be swapped." bug: "352598211" } + +flag { + name: "keyboard_a11y_shortcut_control" + namespace: "input" + description: "Adds shortcuts to toggle and control a11y features" + bug: "373458181" +} diff --git a/core/java/android/hardware/radio/RadioAlert.aidl b/core/java/android/hardware/radio/RadioAlert.aidl new file mode 100644 index 0000000000000000000000000000000000000000..17f4fc7e9a137105a544ac17bcedb4142a49f029 --- /dev/null +++ b/core/java/android/hardware/radio/RadioAlert.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.radio; + +/** @hide */ +parcelable RadioAlert; \ No newline at end of file diff --git a/core/java/android/hardware/radio/RadioAlert.java b/core/java/android/hardware/radio/RadioAlert.java new file mode 100644 index 0000000000000000000000000000000000000000..9b93e73555f0cd524a572ab905e91c55fc36d9ce --- /dev/null +++ b/core/java/android/hardware/radio/RadioAlert.java @@ -0,0 +1,517 @@ +/** + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.radio; + +import android.annotation.FlaggedApi; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Emergency Alert Message + * + *

Alert message can be sent from a radio station of technologies such as HD radio to + * the radio users for some emergency events (see ITU-T X.1303 bis for more info). + * @hide + */ +@FlaggedApi(Flags.FLAG_HD_RADIO_EMERGENCY_ALERT_SYSTEM) +public final class RadioAlert implements Parcelable { + + public static final class Geocode implements Parcelable { + + private final String mValueName; + private final String mValue; + + /** + * Constructor of geocode. + * + * @param valueName Name of geocode value + * @param value Value of geocode + * @hide + */ + public Geocode(@NonNull String valueName, @NonNull String value) { + mValueName = Objects.requireNonNull(valueName, "Geocode value name can not be null"); + mValue = Objects.requireNonNull(value, "Geocode value can not be null"); + } + + private Geocode(Parcel in) { + mValueName = in.readString8(); + mValue = in.readString8(); + } + + public static final @NonNull Creator CREATOR = new Creator() { + @Override + public Geocode createFromParcel(Parcel in) { + return new Geocode(in); + } + + @Override + public Geocode[] newArray(int size) { + return new Geocode[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString8(mValueName); + dest.writeString8(mValue); + } + + @NonNull + @Override + public String toString() { + return "Gecode [valueName=" + mValueName + ", value=" + mValue + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(mValueName, mValue); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Geocode other)) { + return false; + } + + return Objects.equals(mValueName, other.mValueName) + && Objects.equals(mValue, other.mValue); + } + } + + public static final class Coordinate implements Parcelable { + private final double mLatitude; + private final double mLongitude; + + /** + * Constructor of coordinate. + * + * @param latitude Latitude of the coordinate + * @param longitude Longitude of the coordinate + * @hide + */ + public Coordinate(double latitude, double longitude) { + if (latitude < -90.0 || latitude > 90.0) { + throw new IllegalArgumentException("Latitude value should be between -90 and 90"); + } + if (longitude < -180.0 || longitude > 180.0) { + throw new IllegalArgumentException( + "Longitude value should be between -180 and 180"); + } + mLatitude = latitude; + mLongitude = longitude; + } + + private Coordinate(Parcel in) { + mLatitude = in.readDouble(); + mLongitude = in.readDouble(); + } + + public static final @NonNull Creator CREATOR = new Creator() { + @Override + public Coordinate createFromParcel(Parcel in) { + return new Coordinate(in); + } + + @Override + public Coordinate[] newArray(int size) { + return new Coordinate[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeDouble(mLatitude); + dest.writeDouble(mLongitude); + } + + @NonNull + @Override + public String toString() { + return "Coordinate [latitude=" + mLatitude + ", longitude=" + mLongitude + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(mLatitude, mLongitude); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Coordinate other)) { + return false; + } + return mLatitude == other.mLatitude && mLongitude == other.mLongitude; + } + } + + public static final class Polygon implements Parcelable { + + private final List mCoordinates; + + /** + * Constructor of polygon. + * + * @param coordinates Coordinates the polygon is composed of + * @hide + */ + public Polygon(@NonNull List coordinates) { + Objects.requireNonNull(coordinates, "Coordinates can not be null"); + if (coordinates.size() < 4) { + throw new IllegalArgumentException("Number of coordinates must be at least 4"); + } + if (!coordinates.get(0).equals(coordinates.get(coordinates.size() - 1))) { + throw new IllegalArgumentException( + "The last and first coordinates must be the same"); + } + mCoordinates = coordinates; + } + + private Polygon(Parcel in) { + mCoordinates = new ArrayList<>(); + in.readTypedList(mCoordinates, Coordinate.CREATOR); + } + + public static final @NonNull Creator CREATOR = new Creator() { + @Override + public Polygon createFromParcel(Parcel in) { + return new Polygon(in); + } + + @Override + public Polygon[] newArray(int size) { + return new Polygon[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeTypedList(mCoordinates); + } + + @NonNull + @Override + public String toString() { + return "Polygon [coordinates=" + mCoordinates + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(mCoordinates); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Polygon other)) { + return false; + } + return mCoordinates.equals(other.mCoordinates); + } + } + + public static final class AlertArea implements Parcelable { + + private final List mPolygons; + private final List mGeocodes; + + /** + * Constructor of alert area. + * + * @param polygons Polygons used in alert area + * @param geocodes Geocodes used in alert area + * @hide + */ + public AlertArea(@NonNull List polygons, @NonNull List geocodes) { + mPolygons = Objects.requireNonNull(polygons, "Polygons can not be null"); + mGeocodes = Objects.requireNonNull(geocodes, "Geocodes can not be null"); + } + + private AlertArea(Parcel in) { + mPolygons = new ArrayList<>(); + mGeocodes = new ArrayList<>(); + in.readTypedList(mPolygons, Polygon.CREATOR); + in.readTypedList(mGeocodes, Geocode.CREATOR); + } + + public static final @NonNull Creator CREATOR = new Creator() { + @Override + public AlertArea createFromParcel(Parcel in) { + return new AlertArea(in); + } + + @Override + public AlertArea[] newArray(int size) { + return new AlertArea[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeTypedList(mPolygons); + dest.writeTypedList(mGeocodes); + } + + @NonNull + @Override + public String toString() { + return "AlertArea [polygons=" + mPolygons + ", geocodes=" + mGeocodes + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(mPolygons, mGeocodes); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof AlertArea other)) { + return false; + } + + return mPolygons.equals(other.mPolygons) && mGeocodes.equals(other.mGeocodes); + } + } + + public static final class AlertInfo implements Parcelable { + + private final List mCategoryList; + private final int mUrgency; + private final int mSeverity; + private final int mCertainty; + private final String mTextualMessage; + private final List mAreaList; + @Nullable private final String mLanguage; + + /** + * Constructor for alert info. + * + * @param categoryList Array of categories of the subject event of the alert message + * @param urgency The urgency of the subject event of the alert message + * @param severity The severity of the subject event of the alert message + * @param certainty The certainty of the subject event of the alert message + * @param textualMessage Textual descriptions of the subject event + * @param areaList The array of geographic areas to which the alert info segment in which + * it appears applies + * @param language The optional language field of the alert info + * @hide + */ + public AlertInfo(@NonNull List categoryList, int urgency, + int severity, int certainty, String textualMessage, + @NonNull List areaList, @Nullable String language) { + mCategoryList = Objects.requireNonNull(categoryList, "Category list can not be null"); + mUrgency = urgency; + mSeverity = severity; + mCertainty = certainty; + mTextualMessage = textualMessage; + mAreaList = Objects.requireNonNull(areaList, "Area list can not be null"); + mLanguage = language; + } + + private AlertInfo(Parcel in) { + mCategoryList = in.readArrayList(Integer.class.getClassLoader(), Integer.class); + mUrgency = in.readInt(); + mSeverity = in.readInt(); + mCertainty = in.readInt(); + mTextualMessage = in.readString8(); + mAreaList = new ArrayList<>(); + in.readTypedList(mAreaList, AlertArea.CREATOR); + boolean hasLanguage = in.readBoolean(); + if (hasLanguage) { + mLanguage = in.readString8(); + } else { + mLanguage = null; + } + } + + public static final @NonNull Creator CREATOR = new Creator() { + @Override + public AlertInfo createFromParcel(Parcel in) { + return new AlertInfo(in); + } + + @Override + public AlertInfo[] newArray(int size) { + return new AlertInfo[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeList(mCategoryList); + dest.writeInt(mUrgency); + dest.writeInt(mSeverity); + dest.writeInt(mCertainty); + dest.writeString8(mTextualMessage); + dest.writeTypedList(mAreaList); + if (mLanguage == null) { + dest.writeBoolean(false); + } else { + dest.writeBoolean(true); + dest.writeString8(mLanguage); + } + } + + @NonNull + @Override + public String toString() { + return "AlertInfo [categoryList=" + mCategoryList + ", urgency=" + mUrgency + + ", severity=" + mSeverity + ", certainty=" + mCertainty + + ", textualMessage=" + mTextualMessage + ", areaList=" + mAreaList + + ", language=" + mLanguage + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(mCategoryList, mUrgency, mSeverity, mCertainty, mTextualMessage, + mAreaList, mLanguage); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof AlertInfo other)) { + return false; + } + + return mCategoryList.equals(other.mCategoryList) && mUrgency == other.mUrgency + && mSeverity == other.mSeverity && mCertainty == other.mCertainty + && mTextualMessage.equals(other.mTextualMessage) + && mAreaList.equals(other.mAreaList) + && Objects.equals(mLanguage, other.mLanguage); + } + } + + private final int mStatus; + private final int mMessageType; + private final List mInfoList; + + /** + * Constructor of radio alert message. + * + * @param status Status of alert message + * @param messageType Message type of alert message + * @param infoList List of alert info + * @hide + */ + public RadioAlert(int status, int messageType, + @NonNull List infoList) { + mStatus = status; + mMessageType = messageType; + mInfoList = Objects.requireNonNull(infoList, "Alert info list can not be null"); + } + + private RadioAlert(Parcel in) { + mStatus = in.readInt(); + mMessageType = in.readInt(); + mInfoList = in.readParcelableList(new ArrayList<>(), AlertInfo.class.getClassLoader(), + AlertInfo.class); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mStatus); + dest.writeInt(mMessageType); + dest.writeParcelableList(mInfoList, /* flags= */ 0); + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull + @Override + public String toString() { + return "RadioAlert [status=" + mStatus + ", messageType=" + mMessageType + + ", infoList= " + mInfoList + "]"; + } + + @Override + public int hashCode() { + return Objects.hash(mStatus, mMessageType, mInfoList); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof RadioAlert other)) { + return false; + } + + return mStatus == other.mStatus && mMessageType == other.mMessageType + && mInfoList.equals(other.mInfoList); + } + + public static final @NonNull Creator CREATOR = new Creator() { + @Override + public RadioAlert createFromParcel(Parcel in) { + return new RadioAlert(in); + } + + @Override + public RadioAlert[] newArray(int size) { + return new RadioAlert[size]; + } + }; +} diff --git a/core/java/android/net/vcn/VcnFrameworkInitializer.java b/core/java/android/net/vcn/VcnFrameworkInitializer.java new file mode 100644 index 0000000000000000000000000000000000000000..8cb213b306beae5e58b5984ceab1634cac315a9e --- /dev/null +++ b/core/java/android/net/vcn/VcnFrameworkInitializer.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.vcn; + +import android.annotation.Nullable; +import android.app.SystemServiceRegistry; +import android.compat.Compatibility; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.SystemProperties; + +/** + * Class for performing registration for VCN service. + * + * @hide + */ +// TODO: Expose it as @SystemApi(client = MODULE_LIBRARIES) +public final class VcnFrameworkInitializer { + /** + * Starting with {@link VANILLA_ICE_CREAM}, Telephony feature flags (e.g. {@link + * PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}) are being checked before returning managers + * that depend on them. If the feature is missing, {@link Context#getSystemService} will return + * null. + * + *

This change is specific to VcnManager. + */ + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) + private static final long ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN = 330902016; + + /** + * The corresponding vendor API for Android V + * + *

Starting with Android V, the vendor API format has switched to YYYYMM. + * + * @see Vendor API + * level + */ + private static final int VENDOR_API_FOR_ANDROID_V = 202404; + + private VcnFrameworkInitializer() {} + + // Suppressing AndroidFrameworkCompatChange because we're querying vendor + // partition SDK level, not application's target SDK version (which BTW we + // also check through Compatibility framework a few lines below). + @Nullable + private static String getVcnFeatureDependency() { + // Check SDK version of the client app. Apps targeting pre-V SDK might + // have not checked for existence of these features. + if (!Compatibility.isChangeEnabled(ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN)) { + return null; + } + + // Check SDK version of the vendor partition. Pre-V devices might have + // incorrectly under-declared telephony features. + final int vendorApiLevel = + SystemProperties.getInt( + "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); + if (vendorApiLevel < VENDOR_API_FOR_ANDROID_V) { + return PackageManager.FEATURE_TELEPHONY; + } else { + return PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION; + } + } + + /** + * Register VCN service to {@link Context}, so that {@link Context#getSystemService} can return + * a VcnManager. + * + * @throws IllegalStateException if this is called anywhere besides {@link + * SystemServiceRegistry}. + */ + public static void registerServiceWrappers() { + SystemServiceRegistry.registerContextAwareService( + VcnManager.VCN_MANAGEMENT_SERVICE_STRING, + VcnManager.class, + (context, serviceBinder) -> { + final String telephonyFeatureToCheck = getVcnFeatureDependency(); + if (telephonyFeatureToCheck != null + && !context.getPackageManager() + .hasSystemFeature(telephonyFeatureToCheck)) { + return null; + } + IVcnManagementService service = + IVcnManagementService.Stub.asInterface(serviceBinder); + return new VcnManager(context, service); + }); + } +} diff --git a/core/java/android/net/vcn/flags.aconfig b/core/java/android/net/vcn/flags.aconfig index dcb363ccf53562a8e7f2a97ac54ccbba9ddaea47..5b306243fc36304f38844a84b1f7c1db7911e808 100644 --- a/core/java/android/net/vcn/flags.aconfig +++ b/core/java/android/net/vcn/flags.aconfig @@ -14,45 +14,4 @@ flag { namespace: "vcn" description: "Feature flag for adjustable safe mode timeout" bug: "317406085" -} - -flag{ - name: "network_metric_monitor" - namespace: "vcn" - description: "Feature flag for enabling network metric monitor" - bug: "282996138" -} - -flag{ - name: "validate_network_on_ipsec_loss" - namespace: "vcn" - description: "Trigger network validation when IPsec packet loss exceeds the threshold" - bug: "329139898" -} - -flag{ - name: "evaluate_ipsec_loss_on_lp_nc_change" - namespace: "vcn" - description: "Re-evaluate IPsec packet loss on LinkProperties or NetworkCapabilities change" - bug: "323238888" -} - -flag{ - name: "enforce_main_user" - namespace: "vcn" - description: "Enforce main user to make VCN HSUM compatible" - bug: "310310661" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag{ - name: "handle_seq_num_leap" - namespace: "vcn" - description: "Do not report bad network when there is a suspected sequence number leap" - bug: "332598276" - metadata { - purpose: PURPOSE_BUGFIX - } } \ No newline at end of file diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java index 49ab15a40a8e2a0f76d3f4d1b403c95bd9363a62..50121278f0e683170ebdb4d29f55d16fd187c86e 100644 --- a/core/java/android/os/BaseBundle.java +++ b/core/java/android/os/BaseBundle.java @@ -21,6 +21,7 @@ import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.content.Intent; import android.util.ArrayMap; import android.util.Log; import android.util.MathUtils; @@ -401,6 +402,9 @@ public class BaseBundle { synchronized (this) { object = unwrapLazyValueFromMapLocked(i, clazz, itemTypes); } + if ((mFlags & Bundle.FLAG_VERIFY_TOKENS_PRESENT) != 0) { + Intent.maybeMarkAsMissingCreatorToken(object); + } } return (clazz != null) ? clazz.cast(object) : (T) object; } diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index a698b9d9721549b610aebf0ca146575d6c847d84..ddcb5c60ab8046ac8f2b79b24a30bf9bdaed9187 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -1031,7 +1031,10 @@ public final class BatteryUsageStats implements Parcelable, Closeable { return this; } - private long getStatsDuration() { + /** + * Returns the duration of the battery session reflected by these stats. + */ + public long getStatsDuration() { if (mStatsDurationMs != -1) { return mStatsDurationMs; } else { diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java index b533225192ba7939b273f01384293e727c988b2c..e68c4ca5c07007266704ba8372a5566df5747827 100644 --- a/core/java/android/os/BatteryUsageStatsQuery.java +++ b/core/java/android/os/BatteryUsageStatsQuery.java @@ -20,6 +20,8 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.util.IntArray; +import com.android.internal.os.MonotonicClock; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -85,8 +87,11 @@ public final class BatteryUsageStatsQuery implements Parcelable { @NonNull private final int[] mUserIds; private final long mMaxStatsAgeMs; - private final long mFromTimestamp; - private final long mToTimestamp; + + private final long mAggregatedFromTimestamp; + private final long mAggregatedToTimestamp; + private long mMonotonicStartTime; + private long mMonotonicEndTime; private final double mMinConsumedPowerThreshold; private final @BatteryConsumer.PowerComponentId int[] mPowerComponents; @@ -96,8 +101,10 @@ public final class BatteryUsageStatsQuery implements Parcelable { : new int[]{UserHandle.USER_ALL}; mMaxStatsAgeMs = builder.mMaxStatsAgeMs; mMinConsumedPowerThreshold = builder.mMinConsumedPowerThreshold; - mFromTimestamp = builder.mFromTimestamp; - mToTimestamp = builder.mToTimestamp; + mAggregatedFromTimestamp = builder.mAggregateFromTimestamp; + mAggregatedToTimestamp = builder.mAggregateToTimestamp; + mMonotonicStartTime = builder.mMonotonicStartTime; + mMonotonicEndTime = builder.mMonotonicEndTime; mPowerComponents = builder.mPowerComponents; } @@ -162,12 +169,28 @@ public final class BatteryUsageStatsQuery implements Parcelable { return mMinConsumedPowerThreshold; } + /** + * Returns the exclusive lower bound of the battery history that should be included in + * the aggregated battery usage stats. + */ + public long getMonotonicStartTime() { + return mMonotonicStartTime; + } + + /** + * Returns the inclusive upper bound of the battery history that should be included in + * the aggregated battery usage stats. + */ + public long getMonotonicEndTime() { + return mMonotonicEndTime; + } + /** * Returns the exclusive lower bound of the stored snapshot timestamps that should be included - * in the aggregation. Ignored if {@link #getToTimestamp()} is zero. + * in the aggregation. Ignored if {@link #getAggregatedToTimestamp()} is zero. */ - public long getFromTimestamp() { - return mFromTimestamp; + public long getAggregatedFromTimestamp() { + return mAggregatedFromTimestamp; } /** @@ -175,8 +198,8 @@ public final class BatteryUsageStatsQuery implements Parcelable { * be included in the aggregation. The default is to include only the current stats * accumulated since the latest battery reset. */ - public long getToTimestamp() { - return mToTimestamp; + public long getAggregatedToTimestamp() { + return mAggregatedToTimestamp; } private BatteryUsageStatsQuery(Parcel in) { @@ -185,8 +208,8 @@ public final class BatteryUsageStatsQuery implements Parcelable { in.readIntArray(mUserIds); mMaxStatsAgeMs = in.readLong(); mMinConsumedPowerThreshold = in.readDouble(); - mFromTimestamp = in.readLong(); - mToTimestamp = in.readLong(); + mAggregatedFromTimestamp = in.readLong(); + mAggregatedToTimestamp = in.readLong(); mPowerComponents = in.createIntArray(); } @@ -197,8 +220,8 @@ public final class BatteryUsageStatsQuery implements Parcelable { dest.writeIntArray(mUserIds); dest.writeLong(mMaxStatsAgeMs); dest.writeDouble(mMinConsumedPowerThreshold); - dest.writeLong(mFromTimestamp); - dest.writeLong(mToTimestamp); + dest.writeLong(mAggregatedFromTimestamp); + dest.writeLong(mAggregatedToTimestamp); dest.writeIntArray(mPowerComponents); } @@ -228,8 +251,10 @@ public final class BatteryUsageStatsQuery implements Parcelable { private int mFlags; private IntArray mUserIds; private long mMaxStatsAgeMs = DEFAULT_MAX_STATS_AGE_MS; - private long mFromTimestamp; - private long mToTimestamp; + private long mMonotonicStartTime = MonotonicClock.UNDEFINED; + private long mMonotonicEndTime = MonotonicClock.UNDEFINED; + private long mAggregateFromTimestamp; + private long mAggregateToTimestamp; private double mMinConsumedPowerThreshold = 0; private @BatteryConsumer.PowerComponentId int[] mPowerComponents; @@ -240,6 +265,17 @@ public final class BatteryUsageStatsQuery implements Parcelable { return new BatteryUsageStatsQuery(this); } + /** + * Specifies the time range for the requested stats, in terms of MonotonicClock + * @param monotonicStartTime Inclusive starting monotonic timestamp + * @param monotonicEndTime Exclusive ending timestamp. Can be MonotonicClock.UNDEFINED + */ + public Builder monotonicTimeRange(long monotonicStartTime, long monotonicEndTime) { + mMonotonicStartTime = monotonicStartTime; + mMonotonicEndTime = monotonicEndTime; + return this; + } + /** * Add a user whose battery stats should be included in the battery usage stats. * {@link UserHandle#USER_ALL} will be used by default if no users are added explicitly. @@ -345,8 +381,8 @@ public final class BatteryUsageStatsQuery implements Parcelable { */ // TODO(b/298459065): switch to monotonic clock public Builder aggregateSnapshots(long fromTimestamp, long toTimestamp) { - mFromTimestamp = fromTimestamp; - mToTimestamp = toTimestamp; + mAggregateFromTimestamp = fromTimestamp; + mAggregateToTimestamp = toTimestamp; return this; } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 479aa98f80de30997dca1feac3d1ef3bbfa6251c..a894833946114760bdb134f660171d95707ae8ad 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -18,6 +18,7 @@ package android.os; import android.Manifest; import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -43,6 +44,8 @@ import com.android.internal.ravenwood.RavenwoodEnvironment; import dalvik.system.VMRuntime; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -1273,6 +1276,47 @@ public class Build { public static final int VANILLA_ICE_CREAM = 35; } + /** @hide */ + @IntDef(value = { + VERSION_CODES_FULL.BASE, + VERSION_CODES_FULL.BASE_1_1, + VERSION_CODES_FULL.CUPCAKE, + VERSION_CODES_FULL.DONUT, + VERSION_CODES_FULL.ECLAIR, + VERSION_CODES_FULL.ECLAIR_0_1, + VERSION_CODES_FULL.ECLAIR_MR1, + VERSION_CODES_FULL.FROYO, + VERSION_CODES_FULL.GINGERBREAD, + VERSION_CODES_FULL.GINGERBREAD_MR1, + VERSION_CODES_FULL.HONEYCOMB, + VERSION_CODES_FULL.HONEYCOMB_MR1, + VERSION_CODES_FULL.HONEYCOMB_MR2, + VERSION_CODES_FULL.ICE_CREAM_SANDWICH, + VERSION_CODES_FULL.ICE_CREAM_SANDWICH_MR1, + VERSION_CODES_FULL.JELLY_BEAN, + VERSION_CODES_FULL.JELLY_BEAN_MR1, + VERSION_CODES_FULL.JELLY_BEAN_MR2, + VERSION_CODES_FULL.KITKAT, + VERSION_CODES_FULL.KITKAT_WATCH, + VERSION_CODES_FULL.LOLLIPOP, + VERSION_CODES_FULL.LOLLIPOP_MR1, + VERSION_CODES_FULL.M, + VERSION_CODES_FULL.N, + VERSION_CODES_FULL.N_MR1, + VERSION_CODES_FULL.O, + VERSION_CODES_FULL.O_MR1, + VERSION_CODES_FULL.P, + VERSION_CODES_FULL.Q, + VERSION_CODES_FULL.R, + VERSION_CODES_FULL.S, + VERSION_CODES_FULL.S_V2, + VERSION_CODES_FULL.TIRAMISU, + VERSION_CODES_FULL.UPSIDE_DOWN_CAKE, + VERSION_CODES_FULL.VANILLA_ICE_CREAM, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SdkIntFull {} + /** * Enumeration of the currently known SDK major and minor version codes. * The numbers increase for every release, and are guaranteed to be ordered @@ -1290,6 +1334,208 @@ public class Build { // Use the last 5 digits for the minor version. This allows the // minor version to be set to CUR_DEVELOPMENT. private static final int SDK_INT_MULTIPLIER = 100000; + + /** + * Android 1.0. + */ + public static final int BASE = VERSION_CODES.BASE * SDK_INT_MULTIPLIER; + + /** + * Android 2.0. + */ + public static final int BASE_1_1 = VERSION_CODES.BASE_1_1 * SDK_INT_MULTIPLIER; + + /** + * Android 3.0. + */ + public static final int CUPCAKE = VERSION_CODES.CUPCAKE * SDK_INT_MULTIPLIER; + + /** + * Android 4.0. + */ + public static final int DONUT = VERSION_CODES.DONUT * SDK_INT_MULTIPLIER; + + /** + * Android 5.0. + */ + public static final int ECLAIR = VERSION_CODES.ECLAIR * SDK_INT_MULTIPLIER; + + /** + * Android 6.0. + */ + public static final int ECLAIR_0_1 = VERSION_CODES.ECLAIR_0_1 * SDK_INT_MULTIPLIER; + + /** + * Android 7.0. + */ + public static final int ECLAIR_MR1 = VERSION_CODES.ECLAIR_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 8.0. + */ + public static final int FROYO = VERSION_CODES.FROYO * SDK_INT_MULTIPLIER; + + /** + * Android 9.0. + */ + public static final int GINGERBREAD = VERSION_CODES.GINGERBREAD * SDK_INT_MULTIPLIER; + + /** + * Android 10.0. + */ + public static final int GINGERBREAD_MR1 = + VERSION_CODES.GINGERBREAD_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 11.0. + */ + public static final int HONEYCOMB = VERSION_CODES.HONEYCOMB * SDK_INT_MULTIPLIER; + + /** + * Android 12.0. + */ + public static final int HONEYCOMB_MR1 = VERSION_CODES.HONEYCOMB_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 13.0. + */ + public static final int HONEYCOMB_MR2 = VERSION_CODES.HONEYCOMB_MR2 * SDK_INT_MULTIPLIER; + + /** + * Android 14.0. + */ + public static final int ICE_CREAM_SANDWICH = + VERSION_CODES.ICE_CREAM_SANDWICH * SDK_INT_MULTIPLIER; + + /** + * Android 15.0. + */ + public static final int ICE_CREAM_SANDWICH_MR1 = + VERSION_CODES.ICE_CREAM_SANDWICH_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 16.0. + */ + public static final int JELLY_BEAN = VERSION_CODES.JELLY_BEAN * SDK_INT_MULTIPLIER; + + /** + * Android 17.0. + */ + public static final int JELLY_BEAN_MR1 = VERSION_CODES.JELLY_BEAN_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 18.0. + */ + public static final int JELLY_BEAN_MR2 = VERSION_CODES.JELLY_BEAN_MR2 * SDK_INT_MULTIPLIER; + + /** + * Android 19.0. + */ + public static final int KITKAT = VERSION_CODES.KITKAT * SDK_INT_MULTIPLIER; + + /** + * Android 20.0. + */ + public static final int KITKAT_WATCH = VERSION_CODES.KITKAT_WATCH * SDK_INT_MULTIPLIER; + + /** + * Android 21.0. + */ + public static final int LOLLIPOP = VERSION_CODES.LOLLIPOP * SDK_INT_MULTIPLIER; + + /** + * Android 22.0. + */ + public static final int LOLLIPOP_MR1 = VERSION_CODES.LOLLIPOP_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 23.0. + */ + public static final int M = VERSION_CODES.M * SDK_INT_MULTIPLIER; + + /** + * Android 24.0. + */ + public static final int N = VERSION_CODES.N * SDK_INT_MULTIPLIER; + + /** + * Android 25.0. + */ + public static final int N_MR1 = VERSION_CODES.N_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 26.0. + */ + public static final int O = VERSION_CODES.O * SDK_INT_MULTIPLIER; + + /** + * Android 27.0. + */ + public static final int O_MR1 = VERSION_CODES.O_MR1 * SDK_INT_MULTIPLIER; + + /** + * Android 28.0. + */ + public static final int P = VERSION_CODES.P * SDK_INT_MULTIPLIER; + + /** + * Android 29.0. + */ + public static final int Q = VERSION_CODES.Q * SDK_INT_MULTIPLIER; + + /** + * Android 30.0. + */ + public static final int R = VERSION_CODES.R * SDK_INT_MULTIPLIER; + + /** + * Android 31.0. + */ + public static final int S = VERSION_CODES.S * SDK_INT_MULTIPLIER; + + /** + * Android 32.0. + */ + public static final int S_V2 = VERSION_CODES.S_V2 * SDK_INT_MULTIPLIER; + + /** + * Android 33.0. + */ + public static final int TIRAMISU = VERSION_CODES.TIRAMISU * SDK_INT_MULTIPLIER; + + /** + * Android 34.0. + */ + public static final int UPSIDE_DOWN_CAKE = + VERSION_CODES.UPSIDE_DOWN_CAKE * SDK_INT_MULTIPLIER; + + /** + * Android 35.0. + */ + public static final int VANILLA_ICE_CREAM = + VERSION_CODES.VANILLA_ICE_CREAM * SDK_INT_MULTIPLIER; + } + + /** + * Obtain the major version encoded in a VERSION_CODES_FULL value. + * This value is guaranteed to be non-negative. + * + * @return The major version encoded in a VERSION_CODES_FULL value + */ + @FlaggedApi(Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME) + public static int getMajorSdkVersion(@SdkIntFull int sdkIntFull) { + return sdkIntFull / VERSION_CODES_FULL.SDK_INT_MULTIPLIER; + } + + /** + * Obtain the minor version encoded in a VERSION_CODES_FULL value. + * This value is guaranteed to be non-negative. + * + * @return The minor version encoded in a VERSION_CODES_FULL value + */ + @FlaggedApi(Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME) + public static int getMinorSdkVersion(@SdkIntFull int sdkIntFull) { + return sdkIntFull % VERSION_CODES_FULL.SDK_INT_MULTIPLIER; } /** diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index ed4037c7d246c061338422ea20c5cce396a0f797..c18fb0c38b8279c072499b3381f6e1c5c1db4679 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -62,6 +62,12 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { @VisibleForTesting static final int FLAG_HAS_BINDERS = 1 << 12; + /** + * Indicates there may be intents with creator tokens contained in this bundle. When unparceled, + * they should be verified if tokens are missing or invalid. + */ + static final int FLAG_VERIFY_TOKENS_PRESENT = 1 << 13; + /** * Status when the Bundle can assert that the underlying Parcel DOES NOT contain @@ -274,6 +280,11 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { return orig; } + /** {@hide} */ + public void setIsIntentExtra() { + mFlags |= FLAG_VERIFY_TOKENS_PRESENT; + } + /** * Mark if this Bundle is okay to "defuse." That is, it's okay for system * processes to ignore any {@link BadParcelableException} encountered when diff --git a/core/java/android/os/CombinedVibration.java b/core/java/android/os/CombinedVibration.java index 77d6cb762e06bf3934dd3e6c61b1d56e195e0b86..f1d3957cc919b3a4072e2f1f7b6de44ae6d5f7cd 100644 --- a/core/java/android/os/CombinedVibration.java +++ b/core/java/android/os/CombinedVibration.java @@ -17,6 +17,7 @@ package android.os; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.TestApi; import android.os.vibrator.Flags; import android.util.SparseArray; @@ -28,6 +29,7 @@ import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; +import java.util.function.Function; /** * A CombinedVibration describes a combination of haptic effects to be performed by one or more @@ -113,6 +115,17 @@ public abstract class CombinedVibration implements Parcelable { @TestApi public abstract long getDuration(); + /** + * Gets the estimated duration of the combined vibration in milliseconds. + * + *

For effects with hardware-dependent constants (e.g. primitive compositions), this returns + * the estimated duration based on the {@link VibratorInfo}. For all other effects this will + * return the same as {@link #getDuration()}. + * + * @hide + */ + public abstract long getDuration(@Nullable SparseArray vibratorInfos); + /** * Returns true if this effect could represent a touch haptic feedback. * @@ -381,6 +394,23 @@ public abstract class CombinedVibration implements Parcelable { return mEffect.getDuration(); } + /** @hide */ + @Override + public long getDuration(@Nullable SparseArray vibratorInfos) { + if (vibratorInfos == null) { + return getDuration(); + } + long maxDuration = 0; + for (int i = 0; i < vibratorInfos.size(); i++) { + long duration = mEffect.getDuration(vibratorInfos.valueAt(i)); + if ((duration == Long.MAX_VALUE) || (duration < 0)) { + return duration; + } + maxDuration = Math.max(maxDuration, duration); + } + return maxDuration; + } + /** @hide */ @Override public boolean isHapticFeedbackCandidate() { @@ -531,10 +561,27 @@ public abstract class CombinedVibration implements Parcelable { @Override public long getDuration() { + return getDuration(idx -> mEffects.valueAt(idx).getDuration()); + } + + /** @hide */ + @Override + public long getDuration(@Nullable SparseArray vibratorInfos) { + if (vibratorInfos == null) { + return getDuration(); + } + return getDuration(idx -> { + VibrationEffect effect = mEffects.valueAt(idx); + VibratorInfo info = vibratorInfos.get(mEffects.keyAt(idx)); + return effect.getDuration(info); + }); + } + + private long getDuration(Function durationFn) { long maxDuration = Long.MIN_VALUE; boolean hasUnknownStep = false; for (int i = 0; i < mEffects.size(); i++) { - long duration = mEffects.valueAt(i).getDuration(); + long duration = durationFn.apply(i); if (duration == Long.MAX_VALUE) { // If any duration is repeating, this combination duration is also repeating. return duration; @@ -750,12 +797,21 @@ public abstract class CombinedVibration implements Parcelable { @Override public long getDuration() { + return getDuration(CombinedVibration::getDuration); + } + + /** @hide */ + @Override + public long getDuration(@Nullable SparseArray vibratorInfos) { + return getDuration(effect -> effect.getDuration(vibratorInfos)); + } + + private long getDuration(Function durationFn) { boolean hasUnknownStep = false; long durations = 0; final int effectCount = mEffects.size(); for (int i = 0; i < effectCount; i++) { - CombinedVibration effect = mEffects.get(i); - long duration = effect.getDuration(); + long duration = durationFn.apply(mEffects.get(i)); if (duration == Long.MAX_VALUE) { // If any duration is repeating, this combination duration is also repeating. return duration; diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java index b2d926044869ee4c0cdd965e0f4a3855eb85776b..6afb8e097121ed2aaa37fcbddb97411c8f80ef4d 100644 --- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java +++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java @@ -754,7 +754,7 @@ public final class MessageQueue { // Idle handles only run if the queue is empty or if the first message // in the queue (possibly a barrier) is due to be handled in the future. if (pendingIdleHandlerCount < 0 - && mNextPollTimeoutMillis != 0) { + && isIdle()) { pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index a55398ac97525399c677ec0f6130007b76bc9b4e..ef1e6c9405f38db196ddc0a81f792c9276f49a17 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -114,6 +114,7 @@ public final class Debug "opengl-tracing", "view-hierarchy", "support_boot_stages", + "app_info", }; /** @@ -1016,14 +1017,14 @@ public final class Debug // send VM_START. System.out.println("Waiting for debugger first packet"); - mWaiting = true; + setWaitingForDebugger(true); while (!isDebuggerConnected()) { try { Thread.sleep(100); } catch (InterruptedException ie) { } } - mWaiting = false; + setWaitingForDebugger(false); System.out.println("Debug.suspendAllAndSentVmStart"); VMDebug.suspendAllAndSendVmStart(); @@ -1049,12 +1050,12 @@ public final class Debug Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1); DdmServer.sendChunk(waitChunk); - mWaiting = true; + setWaitingForDebugger(true); while (!isDebuggerConnected()) { try { Thread.sleep(SPIN_DELAY); } catch (InterruptedException ie) {} } - mWaiting = false; + setWaitingForDebugger(false); System.out.println("Debugger has connected"); @@ -1111,6 +1112,16 @@ public final class Debug return VMDebug.getVmFeatureList(); } + /** + * Set whether the app is waiting for a debugger to connect + * + * @hide + */ + private static void setWaitingForDebugger(boolean waiting) { + mWaiting = waiting; + VMDebug.setWaitingForDebugger(waiting); + } + /** * Returns an array of strings that identify Framework features. This is * used by DDMS to determine what sorts of operations the Framework can diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 2d3dd1b9383b0f6f56c73b7432ccb5f3615e6e22..94768d111ca4e4fd9fc114b33458b4aafd04ae72 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -32,6 +32,8 @@ import android.text.TextUtils; import android.util.Log; import android.widget.Toast; +import com.android.internal.R; + import dalvik.system.VMRuntime; import java.io.BufferedReader; @@ -174,19 +176,6 @@ public class GraphicsEnvironment { nativeToggleAngleAsSystemDriver(enabled); } - /** - * Query to determine the ANGLE driver choice. - */ - private String queryAngleChoice(Context context, Bundle coreSettings, - String packageName) { - if (TextUtils.isEmpty(packageName)) { - Log.v(TAG, "No package name specified; use the system driver"); - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; - } - - return queryAngleChoiceInternal(context, coreSettings, packageName); - } - private int getVulkanVersion(PackageManager pm) { // PackageManager doesn't have an API to retrieve the version of a specific feature, and we // need to avoid retrieving all system features here and looping through them. @@ -403,11 +392,13 @@ public class GraphicsEnvironment { * Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES; which corresponds to the * “angle_gl_driver_selection_pkgs” and “angle_gl_driver_selection_values” settings); if it * forces a choice. + * 3) The per-application ANGLE allowlist contained in the platform. This is an array of + * strings containing package names that should use ANGLE. */ - private String queryAngleChoiceInternal(Context context, Bundle bundle, - String packageName) { + private String queryAngleChoice(Context context, Bundle bundle, String packageName) { // Make sure we have a good package name if (TextUtils.isEmpty(packageName)) { + Log.v(TAG, "No package name specified; use the system driver"); return ANGLE_GL_DRIVER_CHOICE_DEFAULT; } @@ -436,8 +427,8 @@ public class GraphicsEnvironment { Log.v(TAG, " angle_gl_driver_selection_pkgs=" + optInPackages); Log.v(TAG, " angle_gl_driver_selection_values=" + optInValues); - // Make sure we have good settings to use - if (optInPackages.size() == 0 || optInPackages.size() != optInValues.size()) { + // Make sure we have valid settings, if any provided + if (optInPackages.size() != optInValues.size()) { Log.v(TAG, "Global.Settings values are invalid: " + "number of packages: " @@ -449,24 +440,53 @@ public class GraphicsEnvironment { // See if this application is listed in the per-application settings list final int pkgIndex = getPackageIndex(packageName, optInPackages); - - if (pkgIndex < 0) { - Log.v(TAG, packageName + " is not listed in per-application setting"); - return ANGLE_GL_DRIVER_CHOICE_DEFAULT; + if (pkgIndex >= 0) { + mAngleOptInIndex = pkgIndex; + + // The application IS listed in the per-application settings list; and so use the + // setting--choosing the current system driver if the setting is "default" + String optInValue = optInValues.get(pkgIndex); + Log.v( + TAG, + "ANGLE Developer option for '" + + packageName + + "' " + + "set to: '" + + optInValue + + "'"); + if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) { + return ANGLE_GL_DRIVER_CHOICE_ANGLE; + } else if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE)) { + return ANGLE_GL_DRIVER_CHOICE_NATIVE; + } } - mAngleOptInIndex = pkgIndex; - // The application IS listed in the per-application settings list; and so use the - // setting--choosing the current system driver if the setting is "default" - String optInValue = optInValues.get(pkgIndex); - Log.v(TAG, - "ANGLE Developer option for '" + packageName + "' " - + "set to: '" + optInValue + "'"); - if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE)) { - return ANGLE_GL_DRIVER_CHOICE_ANGLE; - } else if (optInValue.equals(ANGLE_GL_DRIVER_CHOICE_NATIVE)) { - return ANGLE_GL_DRIVER_CHOICE_NATIVE; + Log.v(TAG, packageName + " is not listed in per-application setting"); + + // Check the per-device allowlist shipped in the platform + if (android.os.Flags.enableAngleAllowList()) { + String[] angleAllowListPackages = + context.getResources().getStringArray(R.array.config_angleAllowList); + + String allowListPackageList = String.join(" ", angleAllowListPackages); + Log.v(TAG, "ANGLE allowlist from config: " + allowListPackageList); + + for (String allowedPackage : angleAllowListPackages) { + if (allowedPackage.equals(packageName)) { + Log.v( + TAG, + "Package name " + + packageName + + " is listed in config_angleAllowList, enabling ANGLE"); + return ANGLE_GL_DRIVER_CHOICE_ANGLE; + } + } + Log.v( + TAG, + packageName + + " is not listed in ANGLE allowlist or settings, returning default"); } + // The user either chose default or an invalid value; go with the default driver. return ANGLE_GL_DRIVER_CHOICE_DEFAULT; } diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index a1b75034442e2396b7089e726fff601309db6d8e..590ddb404b63a545fbe28522ecac5a982142cce6 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -122,3 +122,6 @@ per-file StatsBootstrapAtom.aidl = file:/services/core/java/com/android/server/s per-file StatsBootstrapAtomValue.aidl = file:/services/core/java/com/android/server/stats/OWNERS per-file StatsBootstrapAtomService.java = file:/services/core/java/com/android/server/stats/OWNERS per-file StatsServiceManager.java = file:/services/core/java/com/android/server/stats/OWNERS + +# Dropbox +per-file DropBoxManager* = mwachens@google.com diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 346ee7ca4f871e6ca7e0bbf8211e4d6669993e68..71d29af6cf0251f714ecd43e8747f751a77c45b5 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -41,6 +41,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.util.Preconditions; import com.android.sdksandbox.flags.Flags; +import dalvik.system.VMDebug; import dalvik.system.VMRuntime; import libcore.io.IoUtils; @@ -1410,6 +1411,7 @@ public class Process { public static void setArgV0(@NonNull String text) { sArgV0 = text; setArgV0Native(text); + VMDebug.setCurrentProcessName(text); } private static native void setArgV0Native(String text); diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java index 80c24a9003e8867ae3b2ec3e58351febce794f47..023359726f90a7cbe942a12a017f51c443e3dfca 100644 --- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java +++ b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java @@ -712,7 +712,7 @@ public final class MessageQueue { // Idle handles only run if the queue is empty or if the first message // in the queue (possibly a barrier) is due to be handled in the future. if (pendingIdleHandlerCount < 0 - && mNextPollTimeoutMillis != 0) { + && isIdle()) { pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { diff --git a/core/java/android/os/StatsBootstrapAtomValue.aidl b/core/java/android/os/StatsBootstrapAtomValue.aidl index b59bc062648f9e26fa640fc25153a735771fee50..b31eb6f78355441eaf34c1ede9d4184582f111ec 100644 --- a/core/java/android/os/StatsBootstrapAtomValue.aidl +++ b/core/java/android/os/StatsBootstrapAtomValue.aidl @@ -19,12 +19,36 @@ package android.os; * * @hide */ -union StatsBootstrapAtomValue { - boolean boolValue; - int intValue; - long longValue; - float floatValue; - String stringValue; - byte[] bytesValue; - String[] stringArrayValue; -} \ No newline at end of file +parcelable StatsBootstrapAtomValue { + union Primitive { + boolean boolValue; + int intValue; + long longValue; + float floatValue; + String stringValue; + byte[] bytesValue; + String[] stringArrayValue; + } + + Primitive value; + + parcelable Annotation { + // Match the definitions in + // packages/modules/StatsD/framework/java/android/util/StatsLog.java + // Only supports UIDs for now. + @Backing(type="byte") + enum Id { + NONE, + IS_UID, + } + Id id; + + union Primitive { + boolean boolValue; + int intValue; + } + Primitive value; + } + + Annotation[] annotations; +} diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java index 7f7ef0467e086bca4ae8d4a1a5b59581de6f6c54..f893739fcf28bc0bc2eea27831da6c06afd6532c 100644 --- a/core/java/android/os/UidBatteryConsumer.java +++ b/core/java/android/os/UidBatteryConsumer.java @@ -109,9 +109,11 @@ public final class UidBatteryConsumer extends BatteryConsumer { * Returns the amount of time in milliseconds this UID spent in the specified process state. */ public long getTimeInProcessStateMs(@ProcessState int state) { - Key key = getKey(POWER_COMPONENT_BASE, state); - if (key != null) { - return getUsageDurationMillis(key); + if (state != BatteryConsumer.PROCESS_STATE_UNSPECIFIED) { + Key key = getKey(POWER_COMPONENT_BASE, state); + if (key != null) { + return getUsageDurationMillis(key); + } } return 0; } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index bd3da0d56cbdbb8cb90619206a6a68e9a5fac75e..acf4a2f3ec71e1fbc03b8775847e43cb12a668b4 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -772,9 +772,10 @@ public class UserManager { public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; /** - * When set on the admin user this specifies if the user can remove users. + * When set on the admin user this specifies if the user can remove secondary users. Managed + * profiles and private profiles can still be removed even if this is set on the admin user. * When set on a non-admin secondary user, this specifies if the user can remove itself. - * This restriction has no effect on managed profiles. + * This restriction has no effect when set on managed profiles. * The default value is false. * *

Holders of the permission @@ -793,7 +794,8 @@ public class UserManager { * Specifies if managed profiles of this user can be removed, other than by its profile owner. * The default value is false. *

- * This restriction has no effect on managed profiles. + * This restriction has no effect on managed profiles, and this restriction does not block the + * removal of private profiles of this user. * *

Key for user restrictions. *

Type: Boolean diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index ffc58c537f2afb79adea2740b6b24c8dc0f42c3e..61dd11fd4122375c937534a5e478b60c74a290ad 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -55,6 +55,7 @@ import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; import java.util.function.BiFunction; +import java.util.function.Function; /** * A VibrationEffect describes a haptic effect to be performed by a {@link Vibrator}. @@ -564,6 +565,19 @@ public abstract class VibrationEffect implements Parcelable { @TestApi public abstract long getDuration(); + /** + * Gets the estimated duration of the segment for given vibrator, in milliseconds. + * + *

For effects with hardware-dependent constants (e.g. primitive compositions), this returns + * the estimated duration based on the given {@link VibratorInfo}. For all other effects this + * will return the same as {@link #getDuration()}. + * + * @hide + */ + public long getDuration(@Nullable VibratorInfo vibratorInfo) { + return getDuration(); + } + /** * Checks if a vibrator with a given {@link VibratorInfo} can play this effect as intended. * @@ -904,13 +918,23 @@ public abstract class VibrationEffect implements Parcelable { @Override public long getDuration() { + return getDuration(VibrationEffectSegment::getDuration); + } + + /** @hide */ + @Override + public long getDuration(@Nullable VibratorInfo vibratorInfo) { + return getDuration(segment -> segment.getDuration(vibratorInfo)); + } + + private long getDuration(Function durationFn) { if (mRepeatIndex >= 0) { return Long.MAX_VALUE; } int segmentCount = mSegments.size(); long totalDuration = 0; for (int i = 0; i < segmentCount; i++) { - long segmentDuration = mSegments.get(i).getDuration(); + long segmentDuration = durationFn.apply(mSegments.get(i)); if (segmentDuration < 0) { return segmentDuration; } diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 6a2daeab5f0acaae28d663c4074fd5846c8a29e0..73a74b2f8abc1fd2caba757ff6e67d7100ae485f 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -73,6 +73,9 @@ public class ZygoteProcess { private static final int ZYGOTE_CONNECT_TIMEOUT_MS = 60000; + // How long we wait for an AppZygote to complete pre-loading; this is a pretty conservative + // value that we can probably decrease over time, but we want to be careful here. + public static volatile int sAppZygotePreloadTimeoutMs = 15000; /** * Use a relatively short delay, because for app zygote, this is in the critical path of * service launch. @@ -1099,6 +1102,17 @@ public class ZygoteProcess { throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); } + /** + * Updates the timeout used when preloading code in the app-zygote + * + * @param timeoutMs timeout in milliseconds + */ + public static void setAppZygotePreloadTimeout(int timeoutMs) { + Slog.i(LOG_TAG, "Changing app-zygote preload timeout to " + timeoutMs + " ms."); + + sAppZygotePreloadTimeoutMs = timeoutMs; + } + /** * Instructs the zygote to pre-load the application code for the given Application. * Only the app zygote supports this function. @@ -1106,25 +1120,35 @@ public class ZygoteProcess { public boolean preloadApp(ApplicationInfo appInfo, String abi) throws ZygoteStartFailedEx, IOException { synchronized (mLock) { + int ret; ZygoteState state = openZygoteSocketIfNeeded(abi); - state.mZygoteOutputWriter.write("2"); - state.mZygoteOutputWriter.newLine(); + int previousSocketTimeout = state.mZygoteSessionSocket.getSoTimeout(); - state.mZygoteOutputWriter.write("--preload-app"); - state.mZygoteOutputWriter.newLine(); + try { + state.mZygoteSessionSocket.setSoTimeout(sAppZygotePreloadTimeoutMs); - // Zygote args needs to be strings, so in order to pass ApplicationInfo, - // write it to a Parcel, and base64 the raw Parcel bytes to the other side. - Parcel parcel = Parcel.obtain(); - appInfo.writeToParcel(parcel, 0 /* flags */); - String encodedParcelData = Base64.getEncoder().encodeToString(parcel.marshall()); - parcel.recycle(); - state.mZygoteOutputWriter.write(encodedParcelData); - state.mZygoteOutputWriter.newLine(); + state.mZygoteOutputWriter.write("2"); + state.mZygoteOutputWriter.newLine(); - state.mZygoteOutputWriter.flush(); + state.mZygoteOutputWriter.write("--preload-app"); + state.mZygoteOutputWriter.newLine(); - return (state.mZygoteInputStream.readInt() == 0); + // Zygote args needs to be strings, so in order to pass ApplicationInfo, + // write it to a Parcel, and base64 the raw Parcel bytes to the other side. + Parcel parcel = Parcel.obtain(); + appInfo.writeToParcel(parcel, 0 /* flags */); + String encodedParcelData = Base64.getEncoder().encodeToString(parcel.marshall()); + parcel.recycle(); + state.mZygoteOutputWriter.write(encodedParcelData); + state.mZygoteOutputWriter.newLine(); + + state.mZygoteOutputWriter.flush(); + + ret = state.mZygoteInputStream.readInt(); + } finally { + state.mZygoteSessionSocket.setSoTimeout(previousSocketTimeout); + } + return ret == 0; } } diff --git a/core/java/android/os/vibrator/PrebakedSegment.java b/core/java/android/os/vibrator/PrebakedSegment.java index 39f841226e4e26d9afca3def64915a995f557a1b..b17e82a704bfc3bb2d6fb5d0dede7922286efedf 100644 --- a/core/java/android/os/vibrator/PrebakedSegment.java +++ b/core/java/android/os/vibrator/PrebakedSegment.java @@ -16,6 +16,17 @@ package android.os.vibrator; +import static android.os.VibrationEffect.Composition.PRIMITIVE_CLICK; +import static android.os.VibrationEffect.Composition.PRIMITIVE_THUD; +import static android.os.VibrationEffect.Composition.PRIMITIVE_TICK; +import static android.os.VibrationEffect.EFFECT_CLICK; +import static android.os.VibrationEffect.EFFECT_DOUBLE_CLICK; +import static android.os.VibrationEffect.EFFECT_HEAVY_CLICK; +import static android.os.VibrationEffect.EFFECT_POP; +import static android.os.VibrationEffect.EFFECT_TEXTURE_TICK; +import static android.os.VibrationEffect.EFFECT_THUD; +import static android.os.VibrationEffect.EFFECT_TICK; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; @@ -76,6 +87,32 @@ public final class PrebakedSegment extends VibrationEffectSegment { return -1; } + /** @hide */ + @Override + public long getDuration(@Nullable VibratorInfo vibratorInfo) { + if (vibratorInfo == null) { + return getDuration(); + } + return switch (mEffectId) { + case EFFECT_TICK, + EFFECT_CLICK, + EFFECT_HEAVY_CLICK -> estimateFromPrimitiveDuration(vibratorInfo, PRIMITIVE_CLICK); + case EFFECT_TEXTURE_TICK -> estimateFromPrimitiveDuration(vibratorInfo, PRIMITIVE_TICK); + case EFFECT_THUD -> estimateFromPrimitiveDuration(vibratorInfo, PRIMITIVE_THUD); + case EFFECT_DOUBLE_CLICK -> { + long clickDuration = vibratorInfo.getPrimitiveDuration(PRIMITIVE_CLICK); + yield clickDuration > 0 ? 2 * clickDuration : getDuration(); + } + default -> getDuration(); + }; + } + + private long estimateFromPrimitiveDuration(VibratorInfo vibratorInfo, int primitiveId) { + int duration = vibratorInfo.getPrimitiveDuration(primitiveId); + // Unsupported primitives should be ignored here. + return duration > 0 ? duration : getDuration(); + } + /** @hide */ @Override public boolean areVibrationFeaturesSupported(@NonNull VibratorInfo vibratorInfo) { @@ -89,34 +126,30 @@ public final class PrebakedSegment extends VibrationEffectSegment { } // The vibrator does not have hardware support for the effect, but the effect has fallback // support. Check if a fallback will be available for the effect ID. - switch (mEffectId) { - case VibrationEffect.EFFECT_CLICK: - case VibrationEffect.EFFECT_DOUBLE_CLICK: - case VibrationEffect.EFFECT_HEAVY_CLICK: - case VibrationEffect.EFFECT_TICK: - // Any of these effects are always supported via some form of fallback. - return true; - default: - return false; - } + return switch (mEffectId) { + // Any of these effects are always supported via some form of fallback. + case EFFECT_CLICK, + EFFECT_DOUBLE_CLICK, + EFFECT_HEAVY_CLICK, + EFFECT_TICK -> true; + default -> false; + }; } /** @hide */ @Override public boolean isHapticFeedbackCandidate() { - switch (mEffectId) { - case VibrationEffect.EFFECT_CLICK: - case VibrationEffect.EFFECT_DOUBLE_CLICK: - case VibrationEffect.EFFECT_HEAVY_CLICK: - case VibrationEffect.EFFECT_POP: - case VibrationEffect.EFFECT_TEXTURE_TICK: - case VibrationEffect.EFFECT_THUD: - case VibrationEffect.EFFECT_TICK: - return true; - default: - // VibrationEffect.RINGTONES are not segments that could represent a haptic feedback - return false; - } + return switch (mEffectId) { + case EFFECT_CLICK, + EFFECT_DOUBLE_CLICK, + EFFECT_HEAVY_CLICK, + EFFECT_POP, + EFFECT_TEXTURE_TICK, + EFFECT_THUD, + EFFECT_TICK -> true; + // VibrationEffect.RINGTONES are not segments that could represent a haptic feedback + default -> false; + }; } /** @hide */ @@ -153,27 +186,25 @@ public final class PrebakedSegment extends VibrationEffectSegment { } private static boolean isValidEffectStrength(int strength) { - switch (strength) { - case VibrationEffect.EFFECT_STRENGTH_LIGHT: - case VibrationEffect.EFFECT_STRENGTH_MEDIUM: - case VibrationEffect.EFFECT_STRENGTH_STRONG: - return true; - default: - return false; - } + return switch (strength) { + case VibrationEffect.EFFECT_STRENGTH_LIGHT, + VibrationEffect.EFFECT_STRENGTH_MEDIUM, + VibrationEffect.EFFECT_STRENGTH_STRONG -> true; + default -> false; + }; } /** @hide */ @Override public void validate() { switch (mEffectId) { - case VibrationEffect.EFFECT_CLICK: - case VibrationEffect.EFFECT_DOUBLE_CLICK: - case VibrationEffect.EFFECT_HEAVY_CLICK: - case VibrationEffect.EFFECT_POP: - case VibrationEffect.EFFECT_TEXTURE_TICK: - case VibrationEffect.EFFECT_THUD: - case VibrationEffect.EFFECT_TICK: + case EFFECT_CLICK: + case EFFECT_DOUBLE_CLICK: + case EFFECT_HEAVY_CLICK: + case EFFECT_POP: + case EFFECT_TEXTURE_TICK: + case EFFECT_THUD: + case EFFECT_TICK: break; default: int[] ringtones = VibrationEffect.RINGTONES; diff --git a/core/java/android/os/vibrator/PrimitiveSegment.java b/core/java/android/os/vibrator/PrimitiveSegment.java index 3c84bcda639bc320c65a138f940ac06769b73dbf..91653edd1ba57b0a56db570e9f366fec4ef3a3f8 100644 --- a/core/java/android/os/vibrator/PrimitiveSegment.java +++ b/core/java/android/os/vibrator/PrimitiveSegment.java @@ -75,6 +75,16 @@ public final class PrimitiveSegment extends VibrationEffectSegment { return -1; } + /** @hide */ + @Override + public long getDuration(@Nullable VibratorInfo vibratorInfo) { + if (vibratorInfo == null) { + return getDuration(); + } + int duration = vibratorInfo.getPrimitiveDuration(mPrimitiveId); + return duration > 0 ? duration + mDelay : getDuration(); + } + /** @hide */ @Override public boolean areVibrationFeaturesSupported(@NonNull VibratorInfo vibratorInfo) { diff --git a/core/java/android/os/vibrator/VibrationConfig.java b/core/java/android/os/vibrator/VibrationConfig.java index e6e5a27bd731e2f6774b9f9c188e6df29da963ca..88be96a4aef398da5d033df020e749f06e8b1c30 100644 --- a/core/java/android/os/vibrator/VibrationConfig.java +++ b/core/java/android/os/vibrator/VibrationConfig.java @@ -86,6 +86,7 @@ public class VibrationConfig { private final int mDefaultKeyboardVibrationIntensity; private final boolean mKeyboardVibrationSettingsSupported; + private final int mVibrationPipelineMaxDurationMs; /** @hide */ public VibrationConfig(@Nullable Resources resources) { @@ -106,6 +107,8 @@ public class VibrationConfig { com.android.internal.R.bool.config_ignoreVibrationsOnWirelessCharger); mKeyboardVibrationSettingsSupported = loadBoolean(resources, com.android.internal.R.bool.config_keyboardVibrationSettingsSupported); + mVibrationPipelineMaxDurationMs = loadInteger(resources, + com.android.internal.R.integer.config_vibrationPipelineMaxDuration, 0); mDefaultAlarmVibrationIntensity = loadDefaultIntensity(resources, com.android.internal.R.integer.config_defaultAlarmVibrationIntensity); @@ -220,6 +223,23 @@ public class VibrationConfig { return mRampStepDurationMs; } + /** + * The max duration, in milliseconds, allowed for pipelining vibration requests. + * + *

If the ongoing vibration duration is shorter than this threshold then it should be allowed + * to finish before the next vibration can start. If the ongoing vibration is longer than this + * then it should be cancelled when it's superseded for the new one. + * + * @return the max duration allowed for vibration effect to finish before the next request, or + * zero to disable effect pipelining. + */ + public int getVibrationPipelineMaxDurationMs() { + if (mVibrationPipelineMaxDurationMs < 0) { + return 0; + } + return mVibrationPipelineMaxDurationMs; + } + /** * Whether or not vibrations are ignored if the device is on a wireless charger. * diff --git a/core/java/android/os/vibrator/VibrationEffectSegment.java b/core/java/android/os/vibrator/VibrationEffectSegment.java index e1fb4e36100850f537b431fadd27b4f2da0d9dcb..dadc849dae0a9f9fba69f0ac0bab487ae0ac508f 100644 --- a/core/java/android/os/vibrator/VibrationEffectSegment.java +++ b/core/java/android/os/vibrator/VibrationEffectSegment.java @@ -17,6 +17,7 @@ package android.os.vibrator; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -58,10 +59,23 @@ public abstract class VibrationEffectSegment implements Parcelable { */ public abstract long getDuration(); - /** - * Checks if a given {@link Vibrator} can play this segment as intended. See - * {@link Vibrator#areVibrationFeaturesSupported(VibrationEffect)} for more information about - * what counts as supported by a vibrator, and what counts as not. + /** + * Gets the estimated duration of the segment for given vibrator, in milliseconds. + * + *

For segments with hardware-dependent constants (e.g. primitives), this returns the + * estimated duration based on the given {@link VibratorInfo}. For all other effects this will + * return the same as {@link #getDuration()}. + * + * @hide + */ + public long getDuration(@Nullable VibratorInfo vibratorInfo) { + return getDuration(); + } + + /** + * Checks if a given {@link android.os.Vibrator} can play this segment as intended. See + * {@link android.os.Vibrator#areVibrationFeaturesSupported(VibrationEffect)} for more + * information about what counts as supported by a vibrator, and what counts as not. * * @hide */ diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig index e3b1221b3004df90b53671e9aecc50da3b161914..7ceb948945fdfc92e7468bc0e01fa26ee89b3b02 100644 --- a/core/java/android/os/vibrator/flags.aconfig +++ b/core/java/android/os/vibrator/flags.aconfig @@ -123,4 +123,25 @@ flag { metadata { purpose: PURPOSE_FEATURE } -} \ No newline at end of file +} + +flag { + namespace: "haptics" + name: "primitive_composition_absolute_delay" + is_exported: true + description: "Enables functionality to create primitive compositions with absolute delays" + bug: "373357740" + metadata { + purpose: PURPOSE_FEATURE + } +} + +flag { + namespace: "haptics" + name: "vibration_pipeline_enabled" + description: "Enables functionality to pipeline vibration effects to avoid cancelling short vibrations" + bug: "344494220" + metadata { + purpose: PURPOSE_FEATURE + } +} diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index e59501f2742ac48b9522b8586fe11f3dc294e504..bfefba5b36e67874ab809cfa79e2466be6b4abc9 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -273,3 +273,12 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "platform_skin_temperature_enabled" + is_fixed_read_only: true + is_exported: true + namespace: "android_health_services" + description: "This fixed read-only flag is used to enable platform support for Skin Temperature." + bug: "369872443" +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 594005c3ebd6eb3df1a3eccc8da9bedbf33b1fa0..0be55844b829ab5de8f0967e0ee665ba0abf95cb 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -12845,6 +12845,12 @@ public final class Settings { */ @Readable public static final String CONTEXTUAL_SEARCH_PACKAGE = "contextual_search_package"; + + /** + * Inetger property which determines whether advanced protection is on or not. + * @hide + */ + public static final String ADVANCED_PROTECTION_MODE = "advanced_protection_mode"; } /** diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java new file mode 100644 index 0000000000000000000000000000000000000000..59dd680f17bea644671e1c4d4a5fd88b8755b253 --- /dev/null +++ b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.advancedprotection; + +import android.Manifest; +import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.annotation.SystemService; +import android.content.Context; +import android.os.Binder; +import android.os.RemoteException; +import android.security.Flags; +import android.util.Log; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; + +/** + *

Advanced Protection is a mode that users can enroll their device into, that enhances security + * by enabling features and restrictions across both the platform and user apps. + * + *

This class provides methods to query and control the advanced protection mode + * for the device. + */ +@FlaggedApi(Flags.FLAG_AAPM_API) +@SystemService(Context.ADVANCED_PROTECTION_SERVICE) +public class AdvancedProtectionManager { + private static final String TAG = "AdvancedProtectionM"; + + private final ConcurrentHashMap + mCallbackMap = new ConcurrentHashMap<>(); + + @NonNull + private final IAdvancedProtectionService mService; + + /** @hide */ + public AdvancedProtectionManager(@NonNull IAdvancedProtectionService service) { + mService = service; + } + + /** + * Checks if advanced protection is enabled on the device. + * + * @return {@code true} if advanced protection is enabled, {@code false} otherwise. + */ + @RequiresPermission(Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE) + public boolean isAdvancedProtectionEnabled() { + try { + return mService.isAdvancedProtectionEnabled(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Registers a {@link Callback} to be notified of changes to the Advanced Protection state. + * + *

The provided callback will be called on the specified executor with the updated + * {@link AdvancedProtectionState}. Methods are called when the state changes, as well as once + * on initial registration. + * + * @param executor The executor of where the callback will execute. + * @param callback The {@link Callback} object to register.. + */ + @RequiresPermission(Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE) + public void registerAdvancedProtectionCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull Callback callback) { + if (mCallbackMap.get(callback) != null) { + Log.d(TAG, "registerAdvancedProtectionCallback callback already present"); + return; + } + + IAdvancedProtectionCallback delegate = new IAdvancedProtectionCallback.Stub() { + @Override + public void onAdvancedProtectionChanged(boolean enabled) { + final long identity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> callback.onAdvancedProtectionChanged(enabled)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + }; + + try { + mService.registerAdvancedProtectionCallback(delegate); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + mCallbackMap.put(callback, delegate); + } + + /** + * Unregister an existing {@link Callback}. + * + * @param callback The {@link Callback} object to unregister. + */ + @RequiresPermission(Manifest.permission.QUERY_ADVANCED_PROTECTION_MODE) + public void unregisterAdvancedProtectionCallback(@NonNull Callback callback) { + IAdvancedProtectionCallback delegate = mCallbackMap.get(callback); + if (delegate == null) { + Log.d(TAG, "unregisterAdvancedProtectionCallback callback not present"); + return; + } + + try { + mService.unregisterAdvancedProtectionCallback(delegate); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + mCallbackMap.remove(callback); + } + + /** + * Enables or disables advanced protection on the device. + * + * @param enabled {@code true} to enable advanced protection, {@code false} to disable it. + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.SET_ADVANCED_PROTECTION_MODE) + public void setAdvancedProtectionEnabled(boolean enabled) { + try { + mService.setAdvancedProtectionEnabled(enabled); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * A callback class for monitoring changes to Advanced Protection state + * + *

To register a callback, implement this interface, and register it with + * {@link AdvancedProtectionManager#registerAdvancedProtectionCallback(Executor, Callback)}. + * Methods are called when the state changes, as well as once on initial registration. + */ + @FlaggedApi(Flags.FLAG_AAPM_API) + public interface Callback { + /** + * Called when advanced protection state changes + * @param enabled the new state + */ + void onAdvancedProtectionChanged(boolean enabled); + } +} diff --git a/core/java/android/security/advancedprotection/IAdvancedProtectionCallback.aidl b/core/java/android/security/advancedprotection/IAdvancedProtectionCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..828ce47e652bdf7abca6db816d56dbcf5bf1c0b4 --- /dev/null +++ b/core/java/android/security/advancedprotection/IAdvancedProtectionCallback.aidl @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.advancedprotection; + +/** + * A callback class for monitoring changes to Advanced Protection state + * @hide + */ +oneway interface IAdvancedProtectionCallback { + void onAdvancedProtectionChanged(boolean enabled); +} \ No newline at end of file diff --git a/core/java/android/security/advancedprotection/IAdvancedProtectionService.aidl b/core/java/android/security/advancedprotection/IAdvancedProtectionService.aidl new file mode 100644 index 0000000000000000000000000000000000000000..ef0abf4f23a028433c2ed3de85b89ca0a79a3b0f --- /dev/null +++ b/core/java/android/security/advancedprotection/IAdvancedProtectionService.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.advancedprotection; + +import android.security.advancedprotection.IAdvancedProtectionCallback; + +/** + * Binder interface for apps to communicate with system server implementations of + * AdvancedProtectionService. + * @hide + */ +interface IAdvancedProtectionService { + @EnforcePermission("QUERY_ADVANCED_PROTECTION_MODE") + boolean isAdvancedProtectionEnabled(); + @EnforcePermission("QUERY_ADVANCED_PROTECTION_MODE") + void registerAdvancedProtectionCallback(IAdvancedProtectionCallback callback); + @EnforcePermission("QUERY_ADVANCED_PROTECTION_MODE") + void unregisterAdvancedProtectionCallback(IAdvancedProtectionCallback callback); + @EnforcePermission("SET_ADVANCED_PROTECTION_MODE") + void setAdvancedProtectionEnabled(boolean enabled); +} \ No newline at end of file diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index aedf8e097e6710852e87912014c66a60871c2c92..1d35344e5218e505068cdf051d98660cf9c960c3 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -113,3 +113,10 @@ flag { description: "AFL feature" bug: "365994454" } + +flag { + name: "keystore_grant_api" + namespace: "hardware_backed_security" + description: "Feature flag for exposing KeyStore grant APIs" + bug: "351158708" +} diff --git a/core/java/android/security/forensic/IForensicService.aidl b/core/java/android/security/forensic/IForensicService.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a944b18cb26da4203925491c8eafec4e6d32024b --- /dev/null +++ b/core/java/android/security/forensic/IForensicService.aidl @@ -0,0 +1,32 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.forensic; + +import android.security.forensic.IForensicServiceCommandCallback; +import android.security.forensic.IForensicServiceStateCallback; + +/** + * Binder interface to communicate with ForensicService. + * @hide + */ +interface IForensicService { + void monitorState(IForensicServiceStateCallback callback); + void makeVisible(IForensicServiceCommandCallback callback); + void makeInvisible(IForensicServiceCommandCallback callback); + void enable(IForensicServiceCommandCallback callback); + void disable(IForensicServiceCommandCallback callback); +} diff --git a/core/java/android/security/forensic/IForensicServiceCommandCallback.aidl b/core/java/android/security/forensic/IForensicServiceCommandCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..7fa0c7f726905f9dec5273a162709f98b0c7f613 --- /dev/null +++ b/core/java/android/security/forensic/IForensicServiceCommandCallback.aidl @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.forensic; + +/** + * @hide + */ + oneway interface IForensicServiceCommandCallback { + @Backing(type="int") + enum ErrorCode{ + UNKNOWN = 0, + PERMISSION_DENIED = 1, + INVALID_STATE_TRANSITION = 2, + BACKUP_TRANSPORT_UNAVAILABLE = 3, + DATA_SOURCE_UNAVAILABLE = 3, + } + void onSuccess(); + void onFailure(ErrorCode error); + } diff --git a/core/java/android/security/forensic/IForensicServiceStateCallback.aidl b/core/java/android/security/forensic/IForensicServiceStateCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..0cda35083ffde9bd374474e6e34057c5c7a2dc8a --- /dev/null +++ b/core/java/android/security/forensic/IForensicServiceStateCallback.aidl @@ -0,0 +1,31 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.forensic; + +/** + * @hide + */ + oneway interface IForensicServiceStateCallback { + @Backing(type="int") + enum State{ + UNKNOWN = 0, + INVISIBLE = 1, + VISIBLE = 2, + ENABLED = 3, + } + void onStateChange(State state); + } diff --git a/core/java/android/security/responsible_apis_flags.aconfig b/core/java/android/security/responsible_apis_flags.aconfig index 5457bbee8ad337888ab7bf51d77c327f5cdc6587..b593902a95d492fc84682bca2620f7b54776912f 100644 --- a/core/java/android/security/responsible_apis_flags.aconfig +++ b/core/java/android/security/responsible_apis_flags.aconfig @@ -33,7 +33,6 @@ flag { } } - flag { name: "content_uri_permission_apis" is_exported: true @@ -64,6 +63,14 @@ flag { bug: "339403750" } +flag { + name: "aapm_api" + namespace: "responsible_apis" + description: "Android Advanced Protection Mode Service and Manager" + bug: "352420507" + is_fixed_read_only: true +} + flag { name: "prevent_intent_redirect" namespace: "responsible_apis" diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl index 37a91e720aad124c831bcef63b5b1ca5acf847f4..b384b66bf6807c3a29b13429f97e18573b6ec9cb 100644 --- a/core/java/android/service/notification/INotificationListener.aidl +++ b/core/java/android/service/notification/INotificationListener.aidl @@ -58,7 +58,6 @@ oneway interface INotificationListener void onSuggestedReplySent(String key, in CharSequence reply, int source); void onActionClicked(String key, in Notification.Action action, int source); void onNotificationClicked(String key); - // @deprecated changing allowed adjustments is no longer supported. void onAllowedAdjustmentsChanged(); void onNotificationFeedbackReceived(String key, in NotificationRankingUpdate update, in Bundle feedback); } diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java index 7b7058e83acc01e88ecaee1ccd52b794dde734ce..091b25ab77ceb0663f1520265ae091b86c98c678 100644 --- a/core/java/android/service/notification/NotificationAssistantService.java +++ b/core/java/android/service/notification/NotificationAssistantService.java @@ -319,10 +319,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS * their notifications the assistant can modify. *

Query {@link NotificationManager#getAllowedAssistantAdjustments()} to see what * {@link Adjustment adjustments} you are currently allowed to make.

- * - * @deprecated changing allowed adjustments is no longer supported. */ - @Deprecated public void onAllowedAdjustmentsChanged() { } diff --git a/core/java/android/service/wallpaper/Android.bp b/core/java/android/service/wallpaper/Android.bp deleted file mode 100644 index 552a07d97bf592c43659715871482e25d4eb76de..0000000000000000000000000000000000000000 --- a/core/java/android/service/wallpaper/Android.bp +++ /dev/null @@ -1,24 +0,0 @@ -package { - default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_", - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_base_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_base_license"], -} - -android_library { - - name: "WallpaperSharedLib", - srcs: [ - "*.java", - "I*.aidl", - ], - - libs: ["unsupportedappusage"], - - // Enforce that the library is built against java 8 so that there are - // no compatibility issues with launcher - java_version: "1.8", -} diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index 14d5800e4db718e2b890770edb70bbfb55da4b30..5295b606dd19d5696dde2c38eb26db8fda0e50bc 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -33,6 +33,7 @@ import android.telephony.ims.MediaThreshold; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.annotations.WeaklyReferencedCallback; import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.flags.Flags; @@ -70,6 +71,7 @@ import java.util.stream.Collectors; * its manifest file. Where permissions apply, they are noted in the * appropriate sub-interfaces. */ +@WeaklyReferencedCallback public class TelephonyCallback { private static final String LOG_TAG = "TelephonyCallback"; /** diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 0dec13ff0c02c9fea649d4caa272954f8e6d5dd2..e254bf3e016f7e1c3830dedd83eab43443625bea 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -73,8 +73,11 @@ import java.util.Locale; public abstract class Layout { // These should match the constants in framework/base/libs/hwui/hwui/DrawTextFunctor.h - private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX = 4f; - private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR = 0.2f; + private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX = 0f; + private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR = 0f; + private static final float HIGH_CONTRAST_TEXT_BACKGROUND_CORNER_RADIUS_DP = 5f; + // since we're not using soft light yet, this needs to be much lower than the spec'd 0.8 + private static final float HIGH_CONTRAST_TEXT_BACKGROUND_ALPHA_PERCENTAGE = 0.5f; /** @hide */ @IntDef(prefix = { "BREAK_STRATEGY_" }, value = { @@ -1025,11 +1028,18 @@ public abstract class Layout { var padding = Math.max(HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX, mPaint.getTextSize() * HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR); + var cornerRadius = mPaint.density * HIGH_CONTRAST_TEXT_BACKGROUND_CORNER_RADIUS_DP; + + // We set the alpha on the color itself instead of Paint.setAlpha(), because that function + // actually mutates the color in... *ehem* very strange ways. Also the color might get reset + // for various reasons, which also resets the alpha. + var white = Color.argb(HIGH_CONTRAST_TEXT_BACKGROUND_ALPHA_PERCENTAGE, 1f, 1f, 1f); + var black = Color.argb(HIGH_CONTRAST_TEXT_BACKGROUND_ALPHA_PERCENTAGE, 0f, 0f, 0f); var originalTextColor = mPaint.getColor(); var bgPaint = mWorkPlainPaint; bgPaint.reset(); - bgPaint.setColor(isHighContrastTextDark(originalTextColor) ? Color.WHITE : Color.BLACK); + bgPaint.setColor(isHighContrastTextDark(originalTextColor) ? white : black); bgPaint.setStyle(Paint.Style.FILL); int start = getLineStart(firstLine); @@ -1082,7 +1092,12 @@ public abstract class Layout { private void drawRect() { if (!mLineBackground.isEmpty()) { mLineBackground.inset(-padding, -padding); - canvas.drawRect(mLineBackground, bgPaint); + canvas.drawRoundRect( + mLineBackground, + cornerRadius, + cornerRadius, + bgPaint + ); } } @@ -1104,7 +1119,7 @@ public abstract class Layout { if (hasColorChanged) { mLastColor = textColor; - return isHighContrastTextDark(textColor) ? Color.WHITE : Color.BLACK; + return isHighContrastTextDark(textColor) ? white : black; } return bgPaint.getColor(); diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index 9f54d9fca24b623f39fdcbbeacc301aa2de8d93d..3adbd686cd2c1d0051006b308a9b086215e912cb 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -24,7 +24,7 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.Network; -import android.net.NetworkCapabilities; +import android.net.NetworkInfo; import android.net.SntpClient; import android.os.Build; import android.os.SystemClock; @@ -687,16 +687,8 @@ public abstract class NtpTrustedTime implements TrustedTime { if (connectivityManager == null) { return false; } - final NetworkCapabilities networkCapabilities = - connectivityManager.getNetworkCapabilities(network); - if (networkCapabilities == null) { - if (LOGD) Log.d(TAG, "getNetwork: failed to get network capabilities"); - return false; - } - final boolean isConnectedToInternet = networkCapabilities.hasCapability( - NetworkCapabilities.NET_CAPABILITY_INTERNET) - && networkCapabilities.hasCapability( - NetworkCapabilities.NET_CAPABILITY_VALIDATED); + final NetworkInfo ni = connectivityManager.getNetworkInfo(network); + // This connectivity check is to avoid performing a DNS lookup for the time server on a // unconnected network. There are races to obtain time in Android when connectivity // changes, which means that forceRefresh() can be called by various components before @@ -706,8 +698,8 @@ public abstract class NtpTrustedTime implements TrustedTime { // A side effect of check is that tests that run a fake NTP server on the device itself // will only be able to use it if the active network is connected, even though loopback // addresses are actually reachable. - if (!isConnectedToInternet) { - if (LOGD) Log.d(TAG, "getNetwork: no internet connectivity"); + if (ni == null || !ni.isConnected()) { + if (LOGD) Log.d(TAG, "getNetwork: no connectivity"); return false; } return true; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 8a8022c0206a321e931060ec23691fa97aea6f2e..e940e55bd38b6c028a67f24ffba45aa1072e40f1 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS; import static android.hardware.flags.Flags.FLAG_OVERLAYPROPERTIES_CLASS_API; import static com.android.server.display.feature.flags.Flags.FLAG_HIGHEST_HDR_SDR_RATIO_API; +import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_HAS_ARR_SUPPORT; import android.Manifest; import android.annotation.FlaggedApi; @@ -1265,6 +1266,18 @@ public final class Display { } } + /** + * Returns whether display supports adaptive refresh rate or not. + */ + // TODO(b/372526856) Add a link to the documentation for ARR. + @FlaggedApi(FLAG_ENABLE_HAS_ARR_SUPPORT) + public boolean hasArrSupport() { + synchronized (mLock) { + updateDisplayInfoLocked(); + return mDisplayInfo.hasArrSupport; + } + } + /** *

Returns true if the connected display can be switched into a mode with minimal * post processing.

diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java index 18080e4478fc9bc289c52bc5acbff1018bf9d237..fc7a65dbdc41a14e365f87df9185d6f309cd3e5e 100644 --- a/core/java/android/view/DisplayEventReceiver.java +++ b/core/java/android/view/DisplayEventReceiver.java @@ -24,6 +24,7 @@ import android.os.MessageQueue; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.annotations.WeaklyReferencedCallback; import dalvik.annotation.optimization.FastNative; @@ -40,6 +41,7 @@ import java.lang.ref.WeakReference; * * @hide */ +@WeaklyReferencedCallback public abstract class DisplayEventReceiver { /** diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index cac3e3c25098eba0ca56f3096e510256ab13ebce..26fce904eb5e6394921a6a5a957f6fec2d8245e3 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -197,6 +197,12 @@ public final class DisplayInfo implements Parcelable { */ public float renderFrameRate; + /** + * If {@code true} this Display supports adaptive refresh rates. + * // TODO(b/372526856) Add a link to the documentation for ARR. + */ + public boolean hasArrSupport; + /** * The default display mode. */ @@ -436,6 +442,7 @@ public final class DisplayInfo implements Parcelable { && rotation == other.rotation && modeId == other.modeId && renderFrameRate == other.renderFrameRate + && hasArrSupport == other.hasArrSupport && defaultModeId == other.defaultModeId && userPreferredModeId == other.userPreferredModeId && Arrays.equals(supportedModes, other.supportedModes) @@ -497,6 +504,7 @@ public final class DisplayInfo implements Parcelable { rotation = other.rotation; modeId = other.modeId; renderFrameRate = other.renderFrameRate; + hasArrSupport = other.hasArrSupport; defaultModeId = other.defaultModeId; userPreferredModeId = other.userPreferredModeId; supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); @@ -553,6 +561,7 @@ public final class DisplayInfo implements Parcelable { rotation = source.readInt(); modeId = source.readInt(); renderFrameRate = source.readFloat(); + hasArrSupport = source.readBoolean(); defaultModeId = source.readInt(); userPreferredModeId = source.readInt(); int nModes = source.readInt(); @@ -626,6 +635,7 @@ public final class DisplayInfo implements Parcelable { dest.writeInt(rotation); dest.writeInt(modeId); dest.writeFloat(renderFrameRate); + dest.writeBoolean(hasArrSupport); dest.writeInt(defaultModeId); dest.writeInt(userPreferredModeId); dest.writeInt(supportedModes.length); @@ -871,6 +881,8 @@ public final class DisplayInfo implements Parcelable { sb.append(modeId); sb.append(", renderFrameRate "); sb.append(renderFrameRate); + sb.append(", hasArrSupport "); + sb.append(hasArrSupport); sb.append(", defaultMode "); sb.append(defaultModeId); sb.append(", userPreferredModeId "); diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index d08873c56e6a1392ee4332aef051eeff5b94898e..59c66532fe0be1a500d9b4bc56c5fb0e5edc12ba 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -22,6 +22,7 @@ import static android.view.InsetsControllerProto.CONTROL; import static android.view.InsetsControllerProto.STATE; import static android.view.InsetsSource.ID_IME; import static android.view.InsetsSource.ID_IME_CAPTION_BAR; +import static android.view.ViewProtoLogGroups.IME_INSETS_CONTROLLER; import static android.view.WindowInsets.Type.FIRST; import static android.view.WindowInsets.Type.LAST; import static android.view.WindowInsets.Type.all; @@ -69,6 +70,7 @@ import android.view.inputmethod.InputMethodManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.ImeTracing; import com.android.internal.inputmethod.SoftInputShowHideReason; +import com.android.internal.protolog.ProtoLog; import com.android.internal.util.function.TriFunction; import java.io.PrintWriter; @@ -1920,6 +1922,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final @InsetsType int requestedVisibleTypes = (mRequestedVisibleTypes & ~mask) | (visibleTypes & mask); if (mRequestedVisibleTypes != requestedVisibleTypes) { + ProtoLog.d(IME_INSETS_CONTROLLER, "Setting requestedVisibleTypes to %d (was %d)", + requestedVisibleTypes, mRequestedVisibleTypes); mRequestedVisibleTypes = requestedVisibleTypes; } } diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 326e34b258e55f54bdf54c0378815dce238dad20..bd6ff4c2af02d26334aca4b0d4c020374511e097 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -20,7 +20,6 @@ import static android.view.Display.DEFAULT_DISPLAY; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -36,8 +35,6 @@ import android.os.SystemClock; import android.util.Log; import android.util.SparseArray; -import com.android.hardware.input.Flags; - import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; @@ -4436,7 +4433,6 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @see android.view.View#requestUnbufferedDispatch(int) * @see android.view.View#requestUnbufferedDispatch(MotionEvent) */ - @FlaggedApi(Flags.FLAG_POINTER_COORDS_IS_RESAMPLED_API) public boolean isResampled() { return isResampled; } diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS index 1ea58bcbb76aa34c22b2c99e3eedaab92952715e..80484a6328e0863f578d16319d4e09d6409357a2 100644 --- a/core/java/android/view/OWNERS +++ b/core/java/android/view/OWNERS @@ -88,6 +88,7 @@ per-file OnReceiveContentListener.java = file:/core/java/android/service/autofil per-file OnReceiveContentListener.java = file:/core/java/android/widget/OWNERS per-file ContentInfo.java = file:/core/java/android/service/autofill/OWNERS per-file ContentInfo.java = file:/core/java/android/widget/OWNERS +per-file view_flags.aconfig = file:/services/core/java/com/android/server/wm/OWNERS # WindowManager per-file ContentRecordingSession.aidl = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/java/android/view/RoundScrollbarRenderer.java b/core/java/android/view/RoundScrollbarRenderer.java index 5f6d5e29570e117b8df9b98c6c292e753a2452bb..59c2598f00f031a58ba4b2fb40bde1663858abc6 100644 --- a/core/java/android/view/RoundScrollbarRenderer.java +++ b/core/java/android/view/RoundScrollbarRenderer.java @@ -16,17 +16,26 @@ package android.view; +import static android.util.MathUtils.acos; + +import static java.lang.Math.sin; + import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; +import android.os.SystemProperties; import android.util.DisplayMetrics; +import android.view.flags.Flags; /** * Helper class for drawing round scroll bars on round Wear devices. + * + * @hide */ -class RoundScrollbarRenderer { +public class RoundScrollbarRenderer { + private static final String BLUECHIP_ENABLED_SYSPROP = "persist.cw_build.bluechip.enabled"; // The range of the scrollbar position represented as an angle in degrees. private static final float SCROLLBAR_ANGLE_RANGE = 28.8f; private static final float MAX_SCROLLBAR_ANGLE_SWIPE = 26.3f; // 90% @@ -45,12 +54,15 @@ class RoundScrollbarRenderer { private final Paint mTrackPaint = new Paint(); private final RectF mRect = new RectF(); private final View mParent; - private final int mMaskThickness; + private final float mInset; private float mPreviousMaxScroll = 0; private float mMaxScrollDiff = 0; private float mPreviousCurrentScroll = 0; private float mCurrentScrollDiff = 0; + private float mThumbStrokeWidthAsDegrees = 0; + private boolean mDrawToLeft; + private boolean mUseRefactoredRoundScrollbar; public RoundScrollbarRenderer(View parent) { // Paints for the round scrollbar. @@ -69,29 +81,36 @@ class RoundScrollbarRenderer { // Fetch the resource indicating the thickness of CircularDisplayMask, rounding in the same // way WindowManagerService.showCircularMask does. The scroll bar is inset by this amount so // that it doesn't get clipped. - mMaskThickness = parent.getContext().getResources().getDimensionPixelSize( - com.android.internal.R.dimen.circular_display_mask_thickness); - } + int maskThickness = + parent.getContext() + .getResources() + .getDimensionPixelSize( + com.android.internal.R.dimen.circular_display_mask_thickness); - public void drawRoundScrollbars(Canvas canvas, float alpha, Rect bounds, boolean drawToLeft) { - if (alpha == 0) { - return; - } - // Get information about the current scroll state of the parent view. - float maxScroll = mParent.computeVerticalScrollRange(); - float scrollExtent = mParent.computeVerticalScrollExtent(); - float newScroll = mParent.computeVerticalScrollOffset(); + float thumbWidth = dpToPx(THUMB_WIDTH_DP); + mThumbPaint.setStrokeWidth(thumbWidth); + mTrackPaint.setStrokeWidth(thumbWidth); + mInset = thumbWidth / 2 + maskThickness; + + mUseRefactoredRoundScrollbar = + Flags.useRefactoredRoundScrollbar() + && SystemProperties.getBoolean(BLUECHIP_ENABLED_SYSPROP, false); + } + private float computeScrollExtent(float scrollExtent, float maxScroll) { if (scrollExtent <= 0) { if (!mParent.canScrollVertically(1) && !mParent.canScrollVertically(-1)) { - return; + return -1f; } else { - scrollExtent = 0; + return 0f; } } else if (maxScroll <= scrollExtent) { - return; + return -1f; } + return scrollExtent; + } + private void resizeGradually(float maxScroll, float newScroll) { // Make changes to the VerticalScrollRange happen gradually if (Math.abs(maxScroll - mPreviousMaxScroll) > RESIZING_THRESHOLD_PX && mPreviousMaxScroll != 0) { @@ -106,51 +125,81 @@ class RoundScrollbarRenderer { || Math.abs(mCurrentScrollDiff) > RESIZING_THRESHOLD_PX) { mMaxScrollDiff *= RESIZING_RATE; mCurrentScrollDiff *= RESIZING_RATE; - - maxScroll -= mMaxScrollDiff; - newScroll -= mCurrentScrollDiff; } else { mMaxScrollDiff = 0; mCurrentScrollDiff = 0; } + } - float currentScroll = Math.max(0, newScroll); - float linearThumbLength = scrollExtent; - float thumbWidth = dpToPx(THUMB_WIDTH_DP); - mThumbPaint.setStrokeWidth(thumbWidth); - mTrackPaint.setStrokeWidth(thumbWidth); + public void drawRoundScrollbars(Canvas canvas, float alpha, Rect bounds, boolean drawToLeft) { + if (alpha == 0) { + return; + } + // Get information about the current scroll state of the parent view. + float maxScroll = mParent.computeVerticalScrollRange(); + float scrollExtent = mParent.computeVerticalScrollExtent(); + float newScroll = mParent.computeVerticalScrollOffset(); - setThumbColor(applyAlpha(DEFAULT_THUMB_COLOR, alpha)); - setTrackColor(applyAlpha(DEFAULT_TRACK_COLOR, alpha)); + scrollExtent = computeScrollExtent(scrollExtent, maxScroll); + if (scrollExtent < 0f) { + return; + } - // Normalize the sweep angle for the scroll bar. - float sweepAngle = (linearThumbLength / maxScroll) * SCROLLBAR_ANGLE_RANGE; - sweepAngle = clamp(sweepAngle, MIN_SCROLLBAR_ANGLE_SWIPE, MAX_SCROLLBAR_ANGLE_SWIPE); - // Normalize the start angle so that it falls on the track. - float startAngle = (currentScroll * (SCROLLBAR_ANGLE_RANGE - sweepAngle)) - / (maxScroll - linearThumbLength) - SCROLLBAR_ANGLE_RANGE / 2f; - startAngle = clamp(startAngle, -SCROLLBAR_ANGLE_RANGE / 2f, - SCROLLBAR_ANGLE_RANGE / 2f - sweepAngle); + // Make changes to the VerticalScrollRange happen gradually + resizeGradually(maxScroll, newScroll); + maxScroll -= mMaxScrollDiff; + newScroll -= mCurrentScrollDiff; - // Draw the track and the thumb. - float inset = thumbWidth / 2 + mMaskThickness; - mRect.set( - bounds.left + inset, - bounds.top + inset, - bounds.right - inset, - bounds.bottom - inset); - - if (drawToLeft) { - canvas.drawArc(mRect, 180 + SCROLLBAR_ANGLE_RANGE / 2f, -SCROLLBAR_ANGLE_RANGE, false, - mTrackPaint); - canvas.drawArc(mRect, 180 - startAngle, -sweepAngle, false, mThumbPaint); + applyThumbColor(alpha); + + float sweepAngle = computeSweepAngle(scrollExtent, maxScroll); + float startAngle = + computeStartAngle(Math.max(0, newScroll), sweepAngle, maxScroll, scrollExtent); + + updateBounds(bounds); + + mDrawToLeft = drawToLeft; + drawRoundScrollbars(canvas, startAngle, sweepAngle, alpha); + } + + private void drawRoundScrollbars( + Canvas canvas, float startAngle, float sweepAngle, float alpha) { + if (mUseRefactoredRoundScrollbar) { + draw(canvas, startAngle, sweepAngle, alpha); } else { - canvas.drawArc(mRect, -SCROLLBAR_ANGLE_RANGE / 2f, SCROLLBAR_ANGLE_RANGE, false, - mTrackPaint); - canvas.drawArc(mRect, startAngle, sweepAngle, false, mThumbPaint); + applyTrackColor(alpha); + drawArc(canvas, -SCROLLBAR_ANGLE_RANGE / 2f, SCROLLBAR_ANGLE_RANGE, mTrackPaint); + drawArc(canvas, startAngle, sweepAngle, mThumbPaint); } } + /** Returns true if horizontal bounds are updated */ + private void updateBounds(Rect bounds) { + mRect.set( + bounds.left + mInset, + bounds.top + mInset, + bounds.right - mInset, + bounds.bottom - mInset); + mThumbStrokeWidthAsDegrees = + getVertexAngle((mRect.right - mRect.left) / 2f, mThumbPaint.getStrokeWidth() / 2f); + } + + private float computeSweepAngle(float scrollExtent, float maxScroll) { + // Normalize the sweep angle for the scroll bar. + float sweepAngle = (scrollExtent / maxScroll) * SCROLLBAR_ANGLE_RANGE; + return clamp(sweepAngle, MIN_SCROLLBAR_ANGLE_SWIPE, MAX_SCROLLBAR_ANGLE_SWIPE); + } + + private float computeStartAngle( + float currentScroll, float sweepAngle, float maxScroll, float scrollExtent) { + // Normalize the start angle so that it falls on the track. + float startAngle = + (currentScroll * (SCROLLBAR_ANGLE_RANGE - sweepAngle)) / (maxScroll - scrollExtent) + - SCROLLBAR_ANGLE_RANGE / 2f; + return clamp( + startAngle, -SCROLLBAR_ANGLE_RANGE / 2f, SCROLLBAR_ANGLE_RANGE / 2f - sweepAngle); + } + void getRoundVerticalScrollBarBounds(Rect bounds) { float padding = dpToPx(OUTER_PADDING_DP); final int width = mParent.mRight - mParent.mLeft; @@ -164,10 +213,8 @@ class RoundScrollbarRenderer { private static float clamp(float val, float min, float max) { if (val < min) { return min; - } else if (val > max) { - return max; } else { - return val; + return Math.min(val, max); } } @@ -176,15 +223,17 @@ class RoundScrollbarRenderer { return Color.argb(alphaByte, Color.red(color), Color.green(color), Color.blue(color)); } - private void setThumbColor(int thumbColor) { - if (mThumbPaint.getColor() != thumbColor) { - mThumbPaint.setColor(thumbColor); + private void applyThumbColor(float alpha) { + int color = applyAlpha(DEFAULT_THUMB_COLOR, alpha); + if (mThumbPaint.getColor() != color) { + mThumbPaint.setColor(color); } } - private void setTrackColor(int trackColor) { - if (mTrackPaint.getColor() != trackColor) { - mTrackPaint.setColor(trackColor); + private void applyTrackColor(float alpha) { + int color = applyAlpha(DEFAULT_TRACK_COLOR, alpha); + if (mTrackPaint.getColor() != color) { + mTrackPaint.setColor(color); } } @@ -192,4 +241,88 @@ class RoundScrollbarRenderer { return dp * ((float) mParent.getContext().getResources().getDisplayMetrics().densityDpi) / DisplayMetrics.DENSITY_DEFAULT; } + + private static float getVertexAngle(float edge, float base) { + float edgeSquare = edge * edge * 2; + float baseSquare = base * base; + float gapInRadians = acos(((edgeSquare - baseSquare) / edgeSquare)); + return (float) Math.toDegrees(gapInRadians); + } + + private static float getKiteEdge(float knownEdge, float angleBetweenKnownEdgesInDegrees) { + return (float) (2 * knownEdge * sin(Math.toRadians(angleBetweenKnownEdgesInDegrees / 2))); + } + + private void draw(Canvas canvas, float thumbStartAngle, float thumbSweepAngle, float alpha) { + // Draws the top arc + drawTrack( + canvas, + // The highest point of the top track on a vertical scale. Here the thumb width is + // reduced to account for the arc formed by ROUND stroke style + -SCROLLBAR_ANGLE_RANGE / 2f - mThumbStrokeWidthAsDegrees, + // The lowest point of the top track on a vertical scale. Here the thumb width is + // reduced twice to (a) account for the arc formed by ROUND stroke style (b) gap + // between thumb and top track + thumbStartAngle - mThumbStrokeWidthAsDegrees * 2, + alpha); + // Draws the thumb + drawArc(canvas, thumbStartAngle, thumbSweepAngle, mThumbPaint); + // Draws the bottom arc + drawTrack( + canvas, + // The highest point of the bottom track on a vertical scale. Here the thumb width + // is added twice to (a) account for the arc formed by ROUND stroke style (b) gap + // between thumb and bottom track + (thumbStartAngle + thumbSweepAngle) + mThumbStrokeWidthAsDegrees * 2, + // The lowest point of the top track on a vertical scale. Here the thumb width is + // added to account for the arc formed by ROUND stroke style + SCROLLBAR_ANGLE_RANGE / 2f + mThumbStrokeWidthAsDegrees, + alpha); + } + + private void drawTrack(Canvas canvas, float beginAngle, float endAngle, float alpha) { + // Angular distance between end and begin + float angleBetweenEndAndBegin = endAngle - beginAngle; + // The sweep angle for the track is the angular distance between end and begin less the + // thumb width twice to account for top and bottom arc formed by the ROUND stroke style + float sweepAngle = angleBetweenEndAndBegin - 2 * mThumbStrokeWidthAsDegrees; + + float startAngle = -1f; + float strokeWidth = -1f; + if (sweepAngle > 0f) { + // The angle is greater than 0 which means a normal arc should be drawn with stroke + // width same as the thumb. The ROUND stroke style will cover the top/bottom arc of the + // track + startAngle = beginAngle + mThumbStrokeWidthAsDegrees; + strokeWidth = mThumbPaint.getStrokeWidth(); + } else if (Math.abs(sweepAngle) < 2 * mThumbStrokeWidthAsDegrees) { + // The sweep angle is less than 0 but is still relevant in creating a circle for the + // top/bottom track. The start angle is adjusted to account for being the mid point of + // begin / end angle. + startAngle = beginAngle + angleBetweenEndAndBegin / 2; + // The radius of this circle forms a kite with the radius of the arc drawn for the rect + // with the given angular difference between the arc radius which is used to compute the + // new stroke width. + strokeWidth = getKiteEdge(((mRect.right - mRect.left) / 2), angleBetweenEndAndBegin); + // The opacity is decreased proportionally, if the stroke width of the track is 50% or + // less that that of the thumb + alpha = alpha * Math.min(1f, 2 * strokeWidth / mThumbPaint.getStrokeWidth()); + // As we desire a circle to be drawn, the sweep angle is set to a minimal value + sweepAngle = Float.MIN_NORMAL; + } else { + return; + } + + applyTrackColor(alpha); + mTrackPaint.setStrokeWidth(strokeWidth); + drawArc(canvas, startAngle, sweepAngle, mTrackPaint); + } + + private void drawArc(Canvas canvas, float startAngle, float sweepAngle, Paint paint) { + if (mDrawToLeft) { + canvas.drawArc(mRect, /* startAngle= */ 180 - startAngle, -sweepAngle, false, paint); + } else { + canvas.drawArc(mRect, startAngle, sweepAngle, /* useCenter= */ false, paint); + } + } } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 19e244aa5981292372912818892aacf3da45fcc7..e6de478e3d3d32fc7c048eee30f2238c5f476a2e 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -1810,6 +1810,7 @@ public final class SurfaceControl implements Parcelable { public DisplayMode[] supportedDisplayModes; public int activeDisplayModeId; public float renderFrameRate; + public boolean hasArrSupport; public int[] supportedColorModes; public int activeColorMode; @@ -1827,6 +1828,7 @@ public final class SurfaceControl implements Parcelable { + "supportedDisplayModes=" + Arrays.toString(supportedDisplayModes) + ", activeDisplayModeId=" + activeDisplayModeId + ", renderFrameRate=" + renderFrameRate + + ", hasArrSupport=" + hasArrSupport + ", supportedColorModes=" + Arrays.toString(supportedColorModes) + ", activeColorMode=" + activeColorMode + ", hdrCapabilities=" + hdrCapabilities @@ -1846,13 +1848,14 @@ public final class SurfaceControl implements Parcelable { && Arrays.equals(supportedColorModes, that.supportedColorModes) && activeColorMode == that.activeColorMode && Objects.equals(hdrCapabilities, that.hdrCapabilities) - && preferredBootDisplayMode == that.preferredBootDisplayMode; + && preferredBootDisplayMode == that.preferredBootDisplayMode + && hasArrSupport == that.hasArrSupport; } @Override public int hashCode() { return Objects.hash(Arrays.hashCode(supportedDisplayModes), activeDisplayModeId, - renderFrameRate, activeColorMode, hdrCapabilities); + renderFrameRate, activeColorMode, hdrCapabilities, hasArrSupport); } } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 83b4971c86214e00b351bc89f75755c28c1421b1..82235d252a728058d6914e59cfeb9bd9dab6845b 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -192,7 +192,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall boolean mDrawFinished = false; final Rect mScreenRect = new Rect(); - private final SurfaceSession mSurfaceSession = new SurfaceSession(); private final boolean mLimitedHdrEnabled = Flags.limitedHdr(); SurfaceControl mSurfaceControl; @@ -1549,7 +1548,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private void createBlastSurfaceControls(ViewRootImpl viewRoot, String name, Transaction surfaceUpdateTransaction) { if (mSurfaceControl == null) { - mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) + mSurfaceControl = new SurfaceControl.Builder() .setName(name) .setLocalOwnerView(this) .setParent(viewRoot.updateAndGetBoundsLayer(surfaceUpdateTransaction)) @@ -1559,7 +1558,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } if (mBlastSurfaceControl == null) { - mBlastSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) + mBlastSurfaceControl = new SurfaceControl.Builder() .setName(name + "(BLAST)") .setLocalOwnerView(this) .setParent(mSurfaceControl) @@ -1577,7 +1576,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } if (mBackgroundControl == null) { - mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession) + mBackgroundControl = new SurfaceControl.Builder() .setName("Background for " + name) .setLocalOwnerView(this) .setOpaque(true) @@ -1734,9 +1733,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall mRTLastReportedPosition.top /*positionTop*/, postScaleX, postScaleY); - mRTLastSetCrop.set((int) (clipLeft / postScaleX), (int) (clipTop / postScaleY), - (int) Math.ceil(clipRight / postScaleX), - (int) Math.ceil(clipBottom / postScaleY)); + mRTLastSetCrop.set(clipLeft, clipTop, clipRight, clipBottom); if (DEBUG_POSITION) { Log.d(TAG, String.format("Setting layer crop = [%d, %d, %d, %d] " + "from scale %f, %f", mRTLastSetCrop.left, diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1b62cfdf5dcb31a8773ab51c8833d2a4fd14cbe5..d9092ee737cee0318df13275aac45ff74520d0bc 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -29217,8 +29217,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); } - final SurfaceSession session = new SurfaceSession(); - final SurfaceControl surfaceControl = new SurfaceControl.Builder(session) + final SurfaceControl surfaceControl = new SurfaceControl.Builder() .setName("drag surface") .setParent(root.getSurfaceControl()) .setBufferSize(shadowSize.x, shadowSize.y) @@ -29284,7 +29283,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (token == null) { surface.destroy(); } - session.kill(); surfaceControl.release(); } } diff --git a/core/java/android/view/ViewProtoLogGroups.java b/core/java/android/view/ViewProtoLogGroups.java new file mode 100644 index 0000000000000000000000000000000000000000..099f76189a5034e5fa0e10d915f70b66d7bed499 --- /dev/null +++ b/core/java/android/view/ViewProtoLogGroups.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.annotation.NonNull; +import android.view.inputmethod.Flags; + +import com.android.internal.protolog.ProtoLogGroup; + +import java.util.UUID; + +/** + * Defines logging groups for ProtoLog. + * + * This file is used by the ProtoLogTool to generate optimized logging code. All of its dependencies + * must be included in services.core.wm.protologgroups build target. + * + * @hide + */ +final class ViewProtoLogGroups { + final static ProtoLogGroup IME_INSETS_CONTROLLER = new ProtoLogGroup( + "IME_INSETS_CONTROLLER", "InsetsController", Flags.refactorInsetsController()); + + final static ProtoLogGroup[] ALL_GROUPS = { + IME_INSETS_CONTROLLER + }; +} + diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b921213cc26ccd35121b305c83294ad939f5152d..0efded2d0eb99979d716eba06e3222925366a497 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -118,6 +118,7 @@ import static android.view.flags.Flags.disableDrawWakeLock; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.flags.Flags.sensitiveContentPrematureProtectionRemovedFix; import static android.view.flags.Flags.toolkitFrameRateFunctionEnablingReadOnly; +import static android.view.flags.Flags.toolkitFrameRateTouchBoost25q1; import static android.view.flags.Flags.toolkitFrameRateTypingReadOnly; import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly; import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly; @@ -279,6 +280,7 @@ import com.android.internal.os.IResultReceiver; import com.android.internal.os.SomeArgs; import com.android.internal.policy.DecorView; import com.android.internal.policy.PhoneFallbackEventHandler; +import com.android.internal.protolog.ProtoLog; import com.android.internal.util.FastPrintWriter; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; @@ -839,7 +841,6 @@ public final class ViewRootImpl implements ViewParent, * surfaces can ensure they do not draw into the surface inset region set by the parent window. */ private SurfaceControl mBoundsLayer; - private final SurfaceSession mSurfaceSession = new SurfaceSession(); private final Transaction mTransaction = new Transaction(); private final Transaction mFrameRateTransaction = new Transaction(); @@ -1282,6 +1283,8 @@ public final class ViewRootImpl implements ViewParent, mIsStylusPointerIconEnabled = InputSettings.isStylusPointerIconEnabled(mContext); + initializeProtoLogInProcess(); + String processorOverrideName = context.getResources().getString( R.string.config_inputEventCompatProcessorOverrideClassName); if (processorOverrideName.isEmpty()) { @@ -2708,7 +2711,7 @@ public final class ViewRootImpl implements ViewParent, */ public SurfaceControl updateAndGetBoundsLayer(Transaction t) { if (mBoundsLayer == null) { - mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession) + mBoundsLayer = new SurfaceControl.Builder() .setContainerLayer() .setName("Bounds for - " + getTitle().toString()) .setParent(getSurfaceControl()) @@ -5949,7 +5952,34 @@ public final class ViewRootImpl implements ViewParent, // If no intersection, set bounds to empty. bounds.setEmpty(); } - return !bounds.isEmpty(); + + if (bounds.isEmpty()) { + return false; + } + + if (android.view.accessibility.Flags.focusRectMinSize()) { + adjustAccessibilityFocusedRectBoundsIfNeeded(bounds); + } + + return true; + } + + /** + * Adjusts accessibility focused rect bounds so that they are not invisible. + * + *

Focus bounds smaller than double the stroke width are very hard to see (or invisible). + * Expand the focus bounds if necessary to at least double the stroke width. + * @param bounds The bounds to adjust + */ + @VisibleForTesting + public void adjustAccessibilityFocusedRectBoundsIfNeeded(Rect bounds) { + final int minRectLength = mAccessibilityManager.getAccessibilityFocusStrokeWidth() * 2; + if (bounds.width() < minRectLength || bounds.height() < minRectLength) { + final float missingWidth = Math.max(0, minRectLength - bounds.width()); + final float missingHeight = Math.max(0, minRectLength - bounds.height()); + bounds.inset(-1 * (int) Math.ceil(missingWidth / 2), + -1 * (int) Math.ceil(missingHeight / 2)); + } } private Drawable getAccessibilityFocusedDrawable() { @@ -6971,9 +7001,7 @@ public final class ViewRootImpl implements ViewParent, handleScrollCaptureRequest((IScrollCaptureResponseListener) msg.obj); break; case MSG_PAUSED_FOR_SYNC_TIMEOUT: - Log.e(mTag, "Timedout waiting to unpause for sync"); - mNumPausedForSync = 0; - scheduleTraversals(); + resumeAfterSyncTimeout(); break; case MSG_CHECK_INVALIDATION_IDLE: { long delta; @@ -12777,6 +12805,15 @@ public final class ViewRootImpl implements ViewParent, activeSurfaceSyncGroup.addTransaction(t); } + /** + * Resume rendering after being paused for sync due to a timeout. + */ + private void resumeAfterSyncTimeout() { + Log.e(mTag, "Timedout waiting to unpause for sync mNumPausedForSync=" + mNumPausedForSync); + mNumPausedForSync = 0; + scheduleTraversals(); + } + @Override public SurfaceSyncGroup getOrCreateSurfaceSyncGroup() { boolean newSyncGroup = false; @@ -12804,6 +12841,16 @@ public final class ViewRootImpl implements ViewParent, } }); newSyncGroup = true; + + // If the sync group is marked ready by a timeout, check if rendering is paused and + // if it is, resume rendering and trigger a traversal. + mActiveSurfaceSyncGroup.addSyncCompleteCallback(mExecutor, () -> { + if (mActiveSurfaceSyncGroup != null + && mActiveSurfaceSyncGroup.isComplete() && mNumPausedForSync > 0) { + mHandler.removeMessages(MSG_PAUSED_FOR_SYNC_TIMEOUT); + resumeAfterSyncTimeout(); + } + }); } Trace.instant(Trace.TRACE_TAG_VIEW, @@ -12818,12 +12865,20 @@ public final class ViewRootImpl implements ViewParent, } } - mNumPausedForSync++; - mHandler.removeMessages(MSG_PAUSED_FOR_SYNC_TIMEOUT); - mHandler.sendEmptyMessageDelayed(MSG_PAUSED_FOR_SYNC_TIMEOUT, - 1000 * Build.HW_TIMEOUT_MULTIPLIER); + // The sync group can be marked ready by a timeout. This makes incrementing + // mNumPausedForSync racy. Here we check if the sync group is complete and + // if it is then we don't pause for syncing. + if (!mActiveSurfaceSyncGroup.isComplete()) { + mNumPausedForSync++; + mHandler.removeMessages(MSG_PAUSED_FOR_SYNC_TIMEOUT); + mHandler.sendEmptyMessageDelayed(MSG_PAUSED_FOR_SYNC_TIMEOUT, + 1000 * Build.HW_TIMEOUT_MULTIPLIER); + } else { + Log.d(mTag, "Active sync group is already completed " + + mActiveSurfaceSyncGroup.getName()); + } return mActiveSurfaceSyncGroup; - }; + } private final Executor mSimpleExecutor = Runnable::run; @@ -13054,6 +13109,11 @@ public final class ViewRootImpl implements ViewParent, boolean desiredAction = motionEventAction != MotionEvent.ACTION_OUTSIDE; boolean undesiredType = windowType == TYPE_INPUT_METHOD && sToolkitFrameRateTypingReadOnlyFlagValue; + + // don't suppress touch boost for TYPE_INPUT_METHOD in ViewRootImpl + if (toolkitFrameRateTouchBoost25q1()) { + return desiredAction && shouldEnableDvrr() && getFrameRateBoostOnTouchEnabled(); + } // use toolkitSetFrameRate flag to gate the change return desiredAction && !undesiredType && shouldEnableDvrr() && getFrameRateBoostOnTouchEnabled(); @@ -13378,4 +13438,13 @@ public final class ViewRootImpl implements ViewParent, mCurrentColorMode = colorMode; } + + private static boolean sProtoLogInitialized = false; + + private void initializeProtoLogInProcess() { + if (!sProtoLogInitialized) { + ProtoLog.init(ViewProtoLogGroups.ALL_GROUPS); + sProtoLogInitialized = true; + } + } } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 5129461095a3a848639d8b05988a2706d0d5f1ab..65e99304997956c2e2c36411fd291e2ac86e479c 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -86,7 +86,6 @@ public class WindowlessWindowManager implements IWindowSession { final HashMap mResizeCompletionForWindow = new HashMap(); - private final SurfaceSession mSurfaceSession = new SurfaceSession(); protected final SurfaceControl mRootSurface; private final Configuration mConfiguration; private final IWindowSession mRealWm; @@ -184,13 +183,13 @@ public class WindowlessWindowManager implements IWindowSession { InputChannel outInputChannel, InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame, float[] outSizeCompatScale) { - final SurfaceControl leash = new SurfaceControl.Builder(mSurfaceSession) + final SurfaceControl leash = new SurfaceControl.Builder() .setName(attrs.getTitle().toString() + "Leash") .setCallsite("WindowlessWindowManager.addToDisplay") .setParent(getParentSurface(window, attrs)) .build(); - final SurfaceControl sc = new SurfaceControl.Builder(mSurfaceSession) + final SurfaceControl sc = new SurfaceControl.Builder() .setFormat(attrs.format) .setBLASTLayer() .setName(attrs.getTitle().toString()) diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index c5ca059d1cea16237cce949df4b54d3242875539..60ccb77e1317d31ef9ece2ec86a7b1344ad860aa 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -2288,10 +2288,7 @@ public class AccessibilityNodeInfo implements Parcelable { /** * Gets the node bounds in window coordinates. *

- * When magnification is enabled, the bounds in window are scaled up by magnification scale - * and the positions are also adjusted according to the offset of magnification viewport. - * For example, it returns Rect(-180, -180, 0, 0) for original bounds Rect(10, 10, 100, 100), - * when the magnification scale is 2 and offsets for X and Y are both 200. + * The node bounds returned are not scaled by magnification. *

* * @param outBounds The output node bounds. diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig index 8ffae845de1f11c9c988b21800cb28defe2284ad..820a1fba11adee72580a4e9ca9fc72556e54b4c4 100644 --- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig +++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig @@ -94,6 +94,16 @@ flag { bug: "303131332" } +flag { + namespace: "accessibility" + name: "focus_rect_min_size" + description: "Ensures the a11y focus rect is big enough to be drawn as visible" + bug: "368667566" + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { namespace: "accessibility" name: "force_invert_color" diff --git a/core/java/android/view/flags/refresh_rate_flags.aconfig b/core/java/android/view/flags/refresh_rate_flags.aconfig index 7b049278731dc8559113cf5e499d992c166fa4f7..c31df73fbeae0a939834c89e7e472706e6961547 100644 --- a/core/java/android/view/flags/refresh_rate_flags.aconfig +++ b/core/java/android/view/flags/refresh_rate_flags.aconfig @@ -119,4 +119,12 @@ flag { description: "Feature flag to enable the fix for applyLegacyAnimation for VRR V QPR2" bug: "335874198" is_fixed_read_only: true +} + +flag { + name: "toolkit_frame_rate_touch_boost_25q1" + namespace: "toolkit" + description: "Feature flag to not suppress touch boost for specific windowTypes in VRR V QPR2" + bug: "335874198" + is_exported: true } \ No newline at end of file diff --git a/core/java/android/view/flags/view_flags.aconfig b/core/java/android/view/flags/view_flags.aconfig index 1cf26ab64c09ed370769ce6f9ee5d0dd45d2f941..bb61ae49259cc851e650609590df04f8baf61934 100644 --- a/core/java/android/view/flags/view_flags.aconfig +++ b/core/java/android/view/flags/view_flags.aconfig @@ -116,4 +116,12 @@ flag { description: "Add a SurfaceView composition order control API." bug: "341021569" is_fixed_read_only: true +} + +flag { + name: "use_refactored_round_scrollbar" + namespace: "wear_frameworks" + description: "Use refactored round scrollbar." + bug: "333417898" + is_fixed_read_only: true } \ No newline at end of file diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 1e5c6d8177e144edeb6923fb3fe9d656222f8358..47fc43735c4dbdfc2a1a4621e6d9d44e9ae8aad6 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -2352,6 +2352,13 @@ public final class InputMethodManager { * {@link #RESULT_HIDDEN}. * @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note: * this does not return result of the request. For result use {@param resultReceiver} instead. + * + * @deprecated The {@link ResultReceiver} is not a reliable way of determining whether the + * Input Method is actually shown or hidden. If result is needed, use + * {@link android.view.WindowInsetsController#show} instead and set a + * {@link View.OnApplyWindowInsetsListener} and verify the provided {@link WindowInsets} for + * the visibility of IME. If result is not needed, use {@link #showSoftInput(View, int)} + * instead. */ public boolean showSoftInput(View view, @ShowFlags int flags, ResultReceiver resultReceiver) { return showSoftInput(view, flags, resultReceiver, SoftInputShowHideReason.SHOW_SOFT_INPUT); @@ -2399,6 +2406,14 @@ public final class InputMethodManager { & WindowInsets.Type.ime()) == 0) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_NO_ONGOING_USER_ANIMATION); + if (resultReceiver != null) { + final boolean imeReqVisible = + (viewRootImpl.getInsetsController().getRequestedVisibleTypes() + & WindowInsets.Type.ime()) != 0; + resultReceiver.send( + imeReqVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN + : InputMethodManager.RESULT_SHOWN, null); + } // TODO(b/322992891) handle case of SHOW_IMPLICIT viewRootImpl.getInsetsController().show(WindowInsets.Type.ime(), false /* fromIme */, statsToken); @@ -2531,6 +2546,13 @@ public final class InputMethodManager { * {@link #RESULT_HIDDEN}. * @return {@code true} if a request was sent to system_server, {@code false} otherwise. Note: * this does not return result of the request. For result use {@param resultReceiver} instead. + * + * @deprecated The {@link ResultReceiver} is not a reliable way of determining whether the + * Input Method is actually shown or hidden. If result is needed, use + * {@link android.view.WindowInsetsController#hide} instead and set a + * {@link View.OnApplyWindowInsetsListener} and verify the provided {@link WindowInsets} for + * the visibility of IME. If result is not needed, use + * {@link #hideSoftInputFromView(View, int)} instead. */ public boolean hideSoftInputFromWindow(IBinder windowToken, @HideFlags int flags, ResultReceiver resultReceiver) { @@ -2569,6 +2591,14 @@ public final class InputMethodManager { // TODO(b/322992891) handle case of HIDE_IMPLICIT_ONLY final var viewRootImpl = servedView.getViewRootImpl(); if (viewRootImpl != null) { + if (resultReceiver != null) { + final boolean imeReqVisible = + (viewRootImpl.getInsetsController().getRequestedVisibleTypes() + & WindowInsets.Type.ime()) != 0; + resultReceiver.send( + !imeReqVisible ? InputMethodManager.RESULT_UNCHANGED_HIDDEN + : InputMethodManager.RESULT_HIDDEN, null); + } viewRootImpl.getInsetsController().hide(WindowInsets.Type.ime()); } return true; diff --git a/core/java/android/view/inputmethod/flags.aconfig b/core/java/android/view/inputmethod/flags.aconfig index bae8affcec473f353e70c676a9863531cedf3584..aa4927ee9b9c1cbaf54b3de13f48bf912c4bb9d2 100644 --- a/core/java/android/view/inputmethod/flags.aconfig +++ b/core/java/android/view/inputmethod/flags.aconfig @@ -72,6 +72,17 @@ flag { } } +flag { + name: "consistent_get_current_input_method_info" + namespace: "input_method" + description: "Use BindingController as the source of truth in getCurrentInputMethodInfo" + bug: "355034523" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { name: "ime_switcher_revamp" is_exported: true diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index b7ee0b8a238a8ccbc6d083bf94cb5021c16aa08a..877fa74138feb2b3fcd87fc3164616037729ff9e 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -16,6 +16,8 @@ package android.webkit; +import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.Intent; @@ -25,6 +27,9 @@ import android.net.Uri; import android.os.Message; import android.view.View; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + public class WebChromeClient { /** @@ -547,18 +552,41 @@ public class WebChromeClient { * Parameters used in the {@link #onShowFileChooser} method. */ public static abstract class FileChooserParams { + /** @hide */ + @IntDef(prefix = { "MODE_" }, value = { + MODE_OPEN, + MODE_OPEN_MULTIPLE, + MODE_OPEN_FOLDER, + MODE_SAVE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Mode {} + /** Open single file. Requires that the file exists before allowing the user to pick it. */ public static final int MODE_OPEN = 0; /** Like Open but allows multiple files to be selected. */ public static final int MODE_OPEN_MULTIPLE = 1; - /** Like Open but allows a folder to be selected. The implementation should enumerate - all files selected by this operation. - This feature is not supported at the moment. - @hide */ + /** Like Open but allows a folder to be selected. */ + @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS) public static final int MODE_OPEN_FOLDER = 2; /** Allows picking a nonexistent file and saving it. */ public static final int MODE_SAVE = 3; + /** @hide */ + @IntDef(prefix = { "PERMISSION_MODE_" }, value = { + PERMISSION_MODE_READ, + PERMISSION_MODE_READ_WRITE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PermissionMode {} + + /** File or directory should be opened for reading only. */ + @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS) + public static final int PERMISSION_MODE_READ = 0; + /** File or directory should be opened for read and write. */ + @FlaggedApi(android.webkit.Flags.FLAG_FILE_SYSTEM_ACCESS) + public static final int PERMISSION_MODE_READ_WRITE = 1; + /** * Parse the result returned by the file picker activity. This method should be used with * {@link #createIntent}. Refer to {@link #createIntent} for how to use it. @@ -585,6 +613,7 @@ public class WebChromeClient { /** * Returns file chooser mode. */ + @Mode public abstract int getMode(); /** @@ -615,6 +644,21 @@ public class WebChromeClient { @Nullable public abstract String getFilenameHint(); + /** + * Returns permission mode {@link #PERMISSION_MODE_READ} or + * {@link #PERMISSION_MODE_READ_WRITE} which indicates the intended mode for opening a file + * or directory. + * + * This can be used to determine whether an Intent such as + * {@link android.content.Intent#ACTION_OPEN_DOCUMENT} should be used rather than + * {@link android.content.Intent#ACTION_GET_CONTENT} to choose files. + */ + @FlaggedApi(Flags.FLAG_FILE_SYSTEM_ACCESS) + @PermissionMode + public int getPermissionMode() { + return PERMISSION_MODE_READ; + } + /** * Creates an intent that would start a file picker for file selection. * The Intent supports choosing files from simple file sources available diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index ffe8c80023c41eb45f358cd15f157746ad428aec..b6663992b85183d3b13c68a0f9924c21e0d89c87 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -17,6 +17,7 @@ package android.webkit; import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -1495,7 +1496,13 @@ public class WebView extends AbsoluteLayout * @param context Application Context. * @param callback will be called on the UI thread with {@code true} if initialization is * successful, {@code false} otherwise. + * @deprecated In WebView version 122.0.6174.0 and later, this initialization is done + * automatically, so there is no need to call this API. If called, this API will invoke + * the {@code callback} immediately with {@code true}, given that Safe Browsing + * is enabled and supported on the device. */ + @Deprecated + @FlaggedApi(android.webkit.Flags.FLAG_DEPRECATE_START_SAFE_BROWSING) public static void startSafeBrowsing(@NonNull Context context, @Nullable ValueCallback callback) { getFactory().getStatics().initSafeBrowsing(context, callback); diff --git a/core/java/android/webkit/flags.aconfig b/core/java/android/webkit/flags.aconfig index d1013a92476f265a3f6ea0ba9f4e5db1c9a59273..c9e94d2f57f65653267041c8316da8d6020bb278 100644 --- a/core/java/android/webkit/flags.aconfig +++ b/core/java/android/webkit/flags.aconfig @@ -10,6 +10,14 @@ flag { is_fixed_read_only: true } +flag { + name: "deprecate_start_safe_browsing" + is_exported: true + namespace: "webview" + description: "Deprecating startSafeBrowsing API because it is a NOOP" + bug: "372193372" +} + flag { name: "mainline_apis" is_exported: true @@ -26,3 +34,11 @@ flag { description: "New feature reduce user-agent for webview" bug: "371034303" } + +flag { + name: "file_system_access" + is_exported: true + namespace: "webview" + description: "New APIs required by File System Access" + bug: "40101963" +} diff --git a/core/java/android/widget/RemoteCollectionItemsAdapter.java b/core/java/android/widget/RemoteCollectionItemsAdapter.java index 9b396aeea9eb2c5fd69cf6ec33245fb94284def9..fc09f880ccd46e9bd299d57270e33e1f342e4d1a 100644 --- a/core/java/android/widget/RemoteCollectionItemsAdapter.java +++ b/core/java/android/widget/RemoteCollectionItemsAdapter.java @@ -40,13 +40,15 @@ class RemoteCollectionItemsAdapter extends BaseAdapter { private RemoteCollectionItems mItems; private InteractionHandler mInteractionHandler; private ColorResources mColorResources; + private boolean mOnLightBackground; private SparseIntArray mLayoutIdToViewType; RemoteCollectionItemsAdapter( @NonNull RemoteCollectionItems items, @NonNull InteractionHandler interactionHandler, - @NonNull ColorResources colorResources) { + @NonNull ColorResources colorResources, + boolean onLightBackground) { // View type count can never increase after an adapter has been set on a ListView. // Additionally, decreasing it could inhibit view recycling if the count were to back and // forth between 3-2-3-2 for example. Therefore, the view type count, should be fixed for @@ -56,6 +58,7 @@ class RemoteCollectionItemsAdapter extends BaseAdapter { mItems = items; mInteractionHandler = interactionHandler; mColorResources = colorResources; + mOnLightBackground = onLightBackground; initLayoutIdToViewType(); } @@ -68,7 +71,8 @@ class RemoteCollectionItemsAdapter extends BaseAdapter { void setData( @NonNull RemoteCollectionItems items, @NonNull InteractionHandler interactionHandler, - @NonNull ColorResources colorResources) { + @NonNull ColorResources colorResources, + boolean onLightBackground) { if (mViewTypeCount < items.getViewTypeCount()) { throw new IllegalArgumentException( "RemoteCollectionItemsAdapter cannot increase view type count after creation"); @@ -77,6 +81,7 @@ class RemoteCollectionItemsAdapter extends BaseAdapter { mItems = items; mInteractionHandler = interactionHandler; mColorResources = colorResources; + mOnLightBackground = onLightBackground; initLayoutIdToViewType(); @@ -184,6 +189,7 @@ class RemoteCollectionItemsAdapter extends BaseAdapter { : new AppWidgetHostView.AdapterChildHostView(parent.getContext()); newView.setInteractionHandler(mInteractionHandler); newView.setColorResourcesNoReapply(mColorResources); + newView.setOnLightBackground(mOnLightBackground); newView.updateAppWidget(item); return newView; } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index d7b5211ad9fd08263640d24f26ca9fa567ea8c86..9b6311f35d170660182def0b6998449955d869cf 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -1248,6 +1248,7 @@ public class RemoteViews implements Parcelable, Filter { AdapterView adapterView = (AdapterView) target; Adapter adapter = adapterView.getAdapter(); + boolean onLightBackground = hasFlags(FLAG_USE_LIGHT_BACKGROUND_LAYOUT); // We can reuse the adapter if it's a RemoteCollectionItemsAdapter and the view type // count hasn't increased. Note that AbsListView allocates a fixed size array for view // recycling in setAdapter, so we must call setAdapter again if the number of view types @@ -1255,8 +1256,12 @@ public class RemoteViews implements Parcelable, Filter { if (adapter instanceof RemoteCollectionItemsAdapter && adapter.getViewTypeCount() >= items.getViewTypeCount()) { try { - ((RemoteCollectionItemsAdapter) adapter).setData( - items, params.handler, params.colorResources); + ((RemoteCollectionItemsAdapter) adapter) + .setData( + items, + params.handler, + params.colorResources, + onLightBackground); } catch (Throwable throwable) { // setData should never failed with the validation in the items builder, but if // it does, catch and rethrow. @@ -1266,8 +1271,9 @@ public class RemoteViews implements Parcelable, Filter { } try { - adapterView.setAdapter(new RemoteCollectionItemsAdapter(items, - params.handler, params.colorResources)); + adapterView.setAdapter( + new RemoteCollectionItemsAdapter( + items, params.handler, params.colorResources, onLightBackground)); } catch (Throwable throwable) { // This could throw if the AdapterView somehow doesn't accept BaseAdapter due to // a type error. diff --git a/core/java/android/window/BackEvent.java b/core/java/android/window/BackEvent.java index d3733b71f7ee9f8090e9bab67d350f0aec7f6422..23e572fcd5770d2887ba280a961c67fbac0f99c5 100644 --- a/core/java/android/window/BackEvent.java +++ b/core/java/android/window/BackEvent.java @@ -16,8 +16,13 @@ package android.window; +import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API; +import static com.android.window.flags.Flags.predictiveBackTimestampApi; + +import android.annotation.FlaggedApi; import android.annotation.FloatRange; import android.annotation.IntDef; +import android.util.TimeUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -44,18 +49,25 @@ public final class BackEvent { private final float mTouchX; private final float mTouchY; private final float mProgress; + private final long mFrameTime; @SwipeEdge private final int mSwipeEdge; /** @hide */ public static BackEvent fromBackMotionEvent(BackMotionEvent backMotionEvent) { - return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(), - backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge()); + if (predictiveBackTimestampApi()) { + return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(), + backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge(), + backMotionEvent.getFrameTime()); + } else { + return new BackEvent(backMotionEvent.getTouchX(), backMotionEvent.getTouchY(), + backMotionEvent.getProgress(), backMotionEvent.getSwipeEdge()); + } } /** - * Creates a new {@link BackEvent} instance. + * Creates a new {@link BackEvent} instance with the current uptime as frame time. * * @param touchX Absolute X location of the touch point of this event. * @param touchY Absolute Y location of the touch point of this event. @@ -67,6 +79,26 @@ public final class BackEvent { mTouchY = touchY; mProgress = progress; mSwipeEdge = swipeEdge; + mFrameTime = System.nanoTime() / TimeUtils.NANOS_PER_MS; + } + + /** + * Creates a new {@link BackEvent} instance. + * + * @param touchX Absolute X location of the touch point of this event. + * @param touchY Absolute Y location of the touch point of this event. + * @param progress Value between 0 and 1 on how far along the back gesture is. + * @param swipeEdge Indicates which edge the swipe starts from. + * @param frameTime frame time of the back event. + */ + @FlaggedApi(FLAG_PREDICTIVE_BACK_TIMESTAMP_API) + public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge, + long frameTime) { + mTouchX = touchX; + mTouchY = touchY; + mProgress = progress; + mSwipeEdge = swipeEdge; + mFrameTime = frameTime; } /** @@ -115,13 +147,38 @@ public final class BackEvent { return mSwipeEdge; } + /** + * Returns the frameTime of the BackEvent in milliseconds. Useful for calculating velocity. + */ + @FlaggedApi(FLAG_PREDICTIVE_BACK_TIMESTAMP_API) + public long getFrameTime() { + return mFrameTime; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof BackEvent)) { + return false; + } + final BackEvent that = (BackEvent) other; + return mTouchX == that.mTouchX + && mTouchY == that.mTouchY + && mProgress == that.mProgress + && mSwipeEdge == that.mSwipeEdge + && mFrameTime == that.mFrameTime; + } + @Override public String toString() { return "BackEvent{" + "mTouchX=" + mTouchX + ", mTouchY=" + mTouchY + ", mProgress=" + mProgress - + ", mSwipeEdge" + mSwipeEdge + + ", mSwipeEdge=" + mSwipeEdge + + ", mFrameTime=" + mFrameTime + "ms" + "}"; } } diff --git a/core/java/android/window/BackMotionEvent.java b/core/java/android/window/BackMotionEvent.java index 8ac68abd8d8ea1e39949e721732d0a8fd8210ede..a8ec4eeb039a5e4bde614f4115d27c24a9374e3a 100644 --- a/core/java/android/window/BackMotionEvent.java +++ b/core/java/android/window/BackMotionEvent.java @@ -33,6 +33,7 @@ import android.view.RemoteAnimationTarget; public final class BackMotionEvent implements Parcelable { private final float mTouchX; private final float mTouchY; + private final long mFrameTime; private final float mProgress; private final boolean mTriggerBack; @@ -48,6 +49,7 @@ public final class BackMotionEvent implements Parcelable { * * @param touchX Absolute X location of the touch point of this event. * @param touchY Absolute Y location of the touch point of this event. + * @param frameTime Event time of the corresponding touch event. * @param progress Value between 0 and 1 on how far along the back gesture is. * @param triggerBack Indicates whether the back arrow is in the triggered state or not * @param swipeEdge Indicates which edge the swipe starts from. @@ -57,12 +59,14 @@ public final class BackMotionEvent implements Parcelable { public BackMotionEvent( float touchX, float touchY, + long frameTime, float progress, boolean triggerBack, @BackEvent.SwipeEdge int swipeEdge, @Nullable RemoteAnimationTarget departingAnimationTarget) { mTouchX = touchX; mTouchY = touchY; + mFrameTime = frameTime; mProgress = progress; mTriggerBack = triggerBack; mSwipeEdge = swipeEdge; @@ -76,6 +80,7 @@ public final class BackMotionEvent implements Parcelable { mTriggerBack = in.readBoolean(); mSwipeEdge = in.readInt(); mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR); + mFrameTime = in.readLong(); } @NonNull @@ -104,6 +109,7 @@ public final class BackMotionEvent implements Parcelable { dest.writeBoolean(mTriggerBack); dest.writeInt(mSwipeEdge); dest.writeTypedObject(mDepartingAnimationTarget, flags); + dest.writeLong(mFrameTime); } /** @@ -147,6 +153,13 @@ public final class BackMotionEvent implements Parcelable { return mSwipeEdge; } + /** + * Returns the frame time of the BackMotionEvent in milliseconds. + */ + public long getFrameTime() { + return mFrameTime; + } + /** * Returns the {@link RemoteAnimationTarget} of the top departing application window, * or {@code null} if the top window should not be moved for the current type of back @@ -162,10 +175,11 @@ public final class BackMotionEvent implements Parcelable { return "BackMotionEvent{" + "mTouchX=" + mTouchX + ", mTouchY=" + mTouchY + + ", mFrameTime=" + mFrameTime + "ms" + ", mProgress=" + mProgress + ", mTriggerBack=" + mTriggerBack - + ", mSwipeEdge" + mSwipeEdge - + ", mDepartingAnimationTarget" + mDepartingAnimationTarget + + ", mSwipeEdge=" + mSwipeEdge + + ", mDepartingAnimationTarget=" + mDepartingAnimationTarget + "}"; } } diff --git a/core/java/android/window/BackProgressAnimator.java b/core/java/android/window/BackProgressAnimator.java index 465e11a048f0e7458a2f20eeb5dc77405a43f5d0..a5be58b7b1831db97d628e216134e6edeebbe473 100644 --- a/core/java/android/window/BackProgressAnimator.java +++ b/core/java/android/window/BackProgressAnimator.java @@ -17,6 +17,7 @@ package android.window; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; +import static com.android.window.flags.Flags.predictiveBackTimestampApi; import android.annotation.NonNull; import android.annotation.Nullable; @@ -66,7 +67,8 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL reset(); }; private final DynamicAnimation.OnAnimationUpdateListener mOnBackInvokedFlingUpdateListener = - (animation, progress, velocity) -> updateProgressValue(progress, velocity); + (animation, progress, velocity) -> + updateProgressValue(progress, velocity, animation.getLastFrameTime()); private void setProgress(float progress) { @@ -92,7 +94,9 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL @Override public void onAnimationUpdate(DynamicAnimation animation, float value, float velocity) { - if (mBackInvokedFinishRunnable == null) updateProgressValue(value, velocity); + if (mBackInvokedFinishRunnable == null) { + updateProgressValue(value, velocity, animation.getLastFrameTime()); + } } @@ -137,7 +141,9 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL mLastBackEvent = event; mCallback = callback; mBackAnimationInProgress = true; - updateProgressValue(0, 0); + updateProgressValue(/* progress */ 0, /* velocity */ 0, + /* frameTime */ System.nanoTime() / TimeUtils.NANOS_PER_MS); + onBackProgressed(event); } /** @@ -146,7 +152,8 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL public void reset() { if (mBackCancelledFinishRunnable != null) { // Ensure that last progress value that apps see is 0 - updateProgressValue(0, 0); + updateProgressValue(/* progress */ 0, /* velocity */ 0, + /* frameTime */ System.nanoTime() / TimeUtils.NANOS_PER_MS); invokeBackCancelledRunnable(); } else if (mBackInvokedFinishRunnable != null) { invokeBackInvokedRunnable(); @@ -236,14 +243,20 @@ public class BackProgressAnimator implements DynamicAnimation.OnAnimationUpdateL return mVelocity / SCALE_FACTOR; } - private void updateProgressValue(float progress, float velocity) { + private void updateProgressValue(float progress, float velocity, long frameTime) { mVelocity = velocity; if (mLastBackEvent == null || mCallback == null || !mBackAnimationInProgress) { return; } - mCallback.onProgressUpdate( - new BackEvent(mLastBackEvent.getTouchX(), mLastBackEvent.getTouchY(), - progress / SCALE_FACTOR, mLastBackEvent.getSwipeEdge())); + BackEvent backEvent; + if (predictiveBackTimestampApi()) { + backEvent = new BackEvent(mLastBackEvent.getTouchX(), mLastBackEvent.getTouchY(), + progress / SCALE_FACTOR, mLastBackEvent.getSwipeEdge(), frameTime); + } else { + backEvent = new BackEvent(mLastBackEvent.getTouchX(), mLastBackEvent.getTouchY(), + progress / SCALE_FACTOR, mLastBackEvent.getSwipeEdge()); + } + mCallback.onProgressUpdate(backEvent); } private void invokeBackCancelledRunnable() { diff --git a/core/java/android/window/BackTouchTracker.java b/core/java/android/window/BackTouchTracker.java index 290c494b1bffcdc251353137be87f25a3883868c..39a30253adbdf439e97453ec70db7cfa8286eaeb 100644 --- a/core/java/android/window/BackTouchTracker.java +++ b/core/java/android/window/BackTouchTracker.java @@ -151,6 +151,7 @@ public class BackTouchTracker { return new BackMotionEvent( /* touchX = */ mInitTouchX, /* touchY = */ mInitTouchY, + /* frameTime = */ 0, /* progress = */ 0, /* triggerBack = */ mTriggerBack, /* swipeEdge = */ mSwipeEdge, @@ -235,6 +236,7 @@ public class BackTouchTracker { return new BackMotionEvent( /* touchX = */ mLatestTouchX, /* touchY = */ mLatestTouchY, + /* frameTime = */ 0, /* progress = */ progress, /* triggerBack = */ mTriggerBack, /* swipeEdge = */ mSwipeEdge, diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java index 8e35843e2193819ee4f651ab26ad20c84eea13d3..05dc910b89deb81e3bd765b7e843e1039d2b1cbe 100644 --- a/core/java/android/window/DesktopModeFlags.java +++ b/core/java/android/window/DesktopModeFlags.java @@ -64,7 +64,9 @@ public enum DesktopModeFlags { ENABLE_WINDOWING_EDGE_DRAG_RESIZE(Flags::enableWindowingEdgeDragResize, true), ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS( Flags::enableDesktopWindowingTaskbarRunningApps, true), + // TODO: b/369763947 - remove this once ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS is ramped up ENABLE_DESKTOP_WINDOWING_TRANSITIONS(Flags::enableDesktopWindowingTransitions, false), + ENABLE_DESKTOP_WINDOWING_ENTER_TRANSITIONS(Flags::enableDesktopWindowingTransitions, false), ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS(Flags::enableDesktopWindowingExitTransitions, false), ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS( Flags::enableWindowingTransitionHandlersObservers, false); diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java index 66c35e2fe837f9da92cd2dfc5307e0bd7badf652..8db1f9509757134ace697b0fca5f1d0388115429 100644 --- a/core/java/android/window/ImeOnBackInvokedDispatcher.java +++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java @@ -17,6 +17,7 @@ package android.window; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; +import static com.android.window.flags.Flags.predictiveBackTimestampApi; import android.annotation.NonNull; import android.annotation.Nullable; @@ -235,8 +236,12 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc @Override public void onBackStarted(@NonNull BackEvent backEvent) { try { + long frameTime = 0; + if (predictiveBackTimestampApi()) { + frameTime = backEvent.getFrameTime(); + } mIOnBackInvokedCallback.onBackStarted( - new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), + new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), frameTime, backEvent.getProgress(), false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { @@ -247,8 +252,12 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc @Override public void onBackProgressed(@NonNull BackEvent backEvent) { try { + long frameTime = 0; + if (predictiveBackTimestampApi()) { + frameTime = backEvent.getFrameTime(); + } mIOnBackInvokedCallback.onBackProgressed( - new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), + new BackMotionEvent(backEvent.getTouchX(), backEvent.getTouchY(), frameTime, backEvent.getProgress(), false, backEvent.getSwipeEdge(), null)); } catch (RemoteException e) { diff --git a/core/java/android/window/SurfaceSyncGroup.java b/core/java/android/window/SurfaceSyncGroup.java index 5d14698c82b3ad47521af11aaf8fa80527347979..a68bdc05e20e8502e9cef7cf091e1d93df2edec0 100644 --- a/core/java/android/window/SurfaceSyncGroup.java +++ b/core/java/android/window/SurfaceSyncGroup.java @@ -838,6 +838,16 @@ public final class SurfaceSyncGroup { mHandler.postDelayed(runnable, this, TRANSACTION_READY_TIMEOUT); } + /** + * Returns true if the SurfaceSyncGroup has completed its sync. + * @hide + */ + public boolean isComplete() { + synchronized (mLock) { + return mFinished; + } + } + /** * A frame callback that is used to synchronize SurfaceViews. The owner of the SurfaceView must * implement onFrameStarted when trying to sync the SurfaceView. This is to ensure the sync diff --git a/core/java/android/window/TaskSnapshot.java b/core/java/android/window/TaskSnapshot.java index 20d1b3bd12ae2e1ec5866581f3cc4b263db49c7d..a37bef80ff044ecd7b636ba054f98856ed30a2db 100644 --- a/core/java/android/window/TaskSnapshot.java +++ b/core/java/android/window/TaskSnapshot.java @@ -83,13 +83,16 @@ public class TaskSnapshot implements Parcelable { public static final int REFERENCE_CACHE = 1 << 1; /** This snapshot object is being persistent. */ public static final int REFERENCE_PERSIST = 1 << 2; + /** This snapshot object is being used for content suggestion. */ + public static final int REFERENCE_CONTENT_SUGGESTION = 1 << 3; @IntDef(flag = true, prefix = { "REFERENCE_" }, value = { REFERENCE_BROADCAST, REFERENCE_CACHE, - REFERENCE_PERSIST + REFERENCE_PERSIST, + REFERENCE_CONTENT_SUGGESTION }) @Retention(RetentionPolicy.SOURCE) - @interface ReferenceFlags {} + public @interface ReferenceFlags {} public TaskSnapshot(long id, long captureTime, @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot, diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java index 8e495ec1dc40c81448b255da868f892f7067b6cf..34abf31149255274c990232cfa25f1e5f9707bc8 100644 --- a/core/java/android/window/WindowContainerTransaction.java +++ b/core/java/android/window/WindowContainerTransaction.java @@ -524,6 +524,22 @@ public final class WindowContainerTransaction implements Parcelable { return this; } + /** + * Disables or enables activities to be started in adjacent tasks (see + * {@link FLAG_ACTIVITY_LAUNCH_ADJACENT}) for the specified root of any child tasks. This + * differs from {@link #setLaunchAdjacentFlagRoot(WindowContainerToken)} which controls the + * preferred launch-adjacent target and allows for selectively setting which root tasks can + * support launch-adjacent. + * @hide + */ + @NonNull + public WindowContainerTransaction setDisableLaunchAdjacent( + @NonNull WindowContainerToken container, boolean disabled) { + mHierarchyOps.add(HierarchyOp.createForSetDisableLaunchAdjacent(container.asBinder(), + disabled)); + return this; + } + /** * Starts a task by id. The task is expected to already exist (eg. as a recent task). * @param taskId Id of task to start. @@ -1488,6 +1504,7 @@ public final class WindowContainerTransaction implements Parcelable { public static final int HIERARCHY_OP_TYPE_RESTORE_BACK_NAVIGATION = 20; public static final int HIERARCHY_OP_TYPE_SET_EXCLUDE_INSETS_TYPES = 21; public static final int HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE = 22; + public static final int HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT = 23; // The following key(s) are for use with mLaunchOptions: // When launching a task (eg. from recents), this is the taskId to be launched. @@ -1556,6 +1573,8 @@ public final class WindowContainerTransaction implements Parcelable { private @InsetsType int mExcludeInsetsTypes; + private boolean mLaunchAdjacentDisabled; + public static HierarchyOp createForReparent( @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT) @@ -1644,6 +1663,15 @@ public final class WindowContainerTransaction implements Parcelable { .build(); } + /** Create a hierarchy op for disabling launch adjacent. */ + public static HierarchyOp createForSetDisableLaunchAdjacent(IBinder container, + boolean disabled) { + return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT) + .setContainer(container) + .setLaunchAdjacentDisabled(disabled) + .build(); + } + /** create a hierarchy op for deleting a task **/ public static HierarchyOp createForRemoveTask(@NonNull IBinder container) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REMOVE_TASK) @@ -1695,6 +1723,7 @@ public final class WindowContainerTransaction implements Parcelable { mReparentLeafTaskIfRelaunch = copy.mReparentLeafTaskIfRelaunch; mIsTrimmableFromRecents = copy.mIsTrimmableFromRecents; mExcludeInsetsTypes = copy.mExcludeInsetsTypes; + mLaunchAdjacentDisabled = copy.mLaunchAdjacentDisabled; } protected HierarchyOp(Parcel in) { @@ -1719,6 +1748,7 @@ public final class WindowContainerTransaction implements Parcelable { mReparentLeafTaskIfRelaunch = in.readBoolean(); mIsTrimmableFromRecents = in.readBoolean(); mExcludeInsetsTypes = in.readInt(); + mLaunchAdjacentDisabled = in.readBoolean(); } public int getType() { @@ -1814,13 +1844,11 @@ public final class WindowContainerTransaction implements Parcelable { } /** Denotes whether the parents should also be included in the op. */ - @NonNull public boolean includingParents() { return mIncludingParents; } - /** Set the task to be trimmable */ - @NonNull + /** Denotes whether the task can be trimmable from recents */ public boolean isTrimmableFromRecents() { return mIsTrimmableFromRecents; } @@ -1829,6 +1857,11 @@ public final class WindowContainerTransaction implements Parcelable { return mExcludeInsetsTypes; } + /** Denotes whether launch-adjacent flag is respected from this task or its children */ + public boolean isLaunchAdjacentDisabled() { + return mLaunchAdjacentDisabled; + } + /** Gets a string representation of a hierarchy-op type. */ public static String hopToString(int type) { switch (type) { @@ -1839,6 +1872,8 @@ public final class WindowContainerTransaction implements Parcelable { case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: return "SetAdjacentRoot"; case HIERARCHY_OP_TYPE_LAUNCH_TASK: return "LaunchTask"; case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT: return "SetAdjacentFlagRoot"; + case HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT: + return "SetDisableLaunchAdjacent"; case HIERARCHY_OP_TYPE_PENDING_INTENT: return "PendingIntent"; case HIERARCHY_OP_TYPE_START_SHORTCUT: return "StartShortcut"; case HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER: return "addInsetsFrameProvider"; @@ -1891,6 +1926,10 @@ public final class WindowContainerTransaction implements Parcelable { case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT: sb.append("container=").append(mContainer).append(" clearRoot=").append(mToTop); break; + case HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT: + sb.append("container=").append(mContainer).append(" disabled=") + .append(mLaunchAdjacentDisabled); + break; case HIERARCHY_OP_TYPE_START_SHORTCUT: sb.append("options=").append(mLaunchOptions) .append(" info=").append(mShortcutInfo); @@ -1971,6 +2010,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeBoolean(mReparentLeafTaskIfRelaunch); dest.writeBoolean(mIsTrimmableFromRecents); dest.writeInt(mExcludeInsetsTypes); + dest.writeBoolean(mLaunchAdjacentDisabled); } @Override @@ -2047,6 +2087,8 @@ public final class WindowContainerTransaction implements Parcelable { private @InsetsType int mExcludeInsetsTypes; + private boolean mLaunchAdjacentDisabled; + Builder(int type) { mType = type; } @@ -2153,6 +2195,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } + Builder setLaunchAdjacentDisabled(boolean disabled) { + mLaunchAdjacentDisabled = disabled; + return this; + } + HierarchyOp build() { final HierarchyOp hierarchyOp = new HierarchyOp(mType); hierarchyOp.mContainer = mContainer; @@ -2179,6 +2226,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch; hierarchyOp.mIsTrimmableFromRecents = mIsTrimmableFromRecents; hierarchyOp.mExcludeInsetsTypes = mExcludeInsetsTypes; + hierarchyOp.mLaunchAdjacentDisabled = mLaunchAdjacentDisabled; return hierarchyOp; } diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index 44a374fb7c20b4441391ee416d70f74eedda86c4..c9d458f22463e87908fd29d9563636f333751b6a 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -17,6 +17,7 @@ package android.window; import static com.android.window.flags.Flags.predictiveBackPrioritySystemNavigationObserver; +import static com.android.window.flags.Flags.predictiveBackTimestampApi; import android.annotation.NonNull; import android.annotation.Nullable; @@ -563,7 +564,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } OnBackAnimationCallback animationCallback = getBackAnimationCallback(); if (animationCallback != null - && !(callback instanceof ImeBackAnimationController)) { + && !(callback instanceof ImeBackAnimationController) + && !predictiveBackTimestampApi()) { mProgressAnimator.onBackInvoked(() -> { if (mIsSystemCallback) { mSystemNavigationObserverCallbackRunnable.run(); diff --git a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig index f739622a1b923f68367883100e4bb11c50acda18..235ba3a414275e5d6daa5149a24e6e033205b15e 100644 --- a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig +++ b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig @@ -36,6 +36,13 @@ flag { is_fixed_read_only: true } +flag { + name: "move_to_external_display_shortcut" + namespace: "large_screen_experiences_app_compat" + description: "Whether the move to external display shortcut in overview is available" + bug: "372872848" +} + flag { name: "app_compat_properties_api" is_exported: true diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig index 155494fb3b256b6ecd09857a4f56b08b9ccf4479..0bcc9c1f58c5ff8a0829dbe182be5660303364ec 100644 --- a/core/java/android/window/flags/lse_desktop_experience.aconfig +++ b/core/java/android/window/flags/lse_desktop_experience.aconfig @@ -238,6 +238,13 @@ flag { bug: "356570693" } +flag { + name: "enable_desktop_windowing_enter_transitions" + namespace: "lse_desktop_experience" + description: "Enables enter desktop windowing transition & motion polish changes" + bug: "369763947" +} + flag { name: "enable_desktop_windowing_exit_transitions" namespace: "lse_desktop_experience" @@ -300,6 +307,13 @@ flag { bug: "359523924" } +flag { + name: "enable_restore_to_previous_size_from_desktop_immersive" + namespace: "lse_desktop_experience" + description: "Restores the window bounds to their previous size when exiting desktop immersive" + bug: "372318163" +} + flag { name: "enable_display_focus_in_shell_transitions" namespace: "lse_desktop_experience" @@ -327,3 +341,10 @@ flag { description: "Add new keyboard shortcut of moving a task into next display" bug: "364154795" } + +flag { + name: "enable_drag_to_maximize" + namespace: "lse_desktop_experience" + description: "Enables a switch to change the concequence of dragging a window to the top edge." + bug: "372614715" +} diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index 622f8c817d9971eadc89d579ee10fe5b57020a58..0d235ffad9b557b4954f3478f2ccf506807adaae 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -69,17 +69,6 @@ flag { bug: "291870756" } -flag { - name: "common_surface_animator" - namespace: "windowing_frontend" - description: "A reusable surface animator for default transition" - bug: "326331384" - is_fixed_read_only: true - metadata { - purpose: PURPOSE_BUGFIX - } -} - flag { name: "reduce_keyguard_transitions" namespace: "windowing_frontend" @@ -325,3 +314,11 @@ flag { is_fixed_read_only: true bug: "362938401" } + +flag { + name: "predictive_back_timestamp_api" + namespace: "systemui" + description: "expose timestamp in BackEvent (API extension)" + is_fixed_read_only: true + bug: "362938401" +} diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig index f0ea7a82d76331dbf1d681b6c6d54464cb07c8d7..b7012b68d459c48e1b3ef8f682df6c2f85558de6 100644 --- a/core/java/android/window/flags/windowing_sdk.aconfig +++ b/core/java/android/window/flags/windowing_sdk.aconfig @@ -108,3 +108,10 @@ flag { description: "Makes WindowLayoutInfo accessible without racing in the Activity#onCreate()" bug: "337820752" } + +flag { + namespace: "windowing_sdk" + name: "better_support_non_match_parent_activity" + description: "Relax the assumption of non-match parent activity" + bug: "356277166" +} diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 18c8eb4ec46bb807a224c30b5f67fb11cee4a3dd..de7ad346a7cddbf9e047f55a742c59ed093b17b4 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -1195,7 +1195,12 @@ public class ResolverListAdapter extends BaseAdapter { @Nullable protected Drawable loadIconFromResource(Resources res, int resId) { - return res.getDrawableForDensity(resId, mIconDpi); + try { + return res.getDrawableForDensity(resId, mIconDpi); + } catch (Resources.NotFoundException e) { + Log.e(TAG, "Resource not found", e); + return null; + } } } diff --git a/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java b/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java index d4fe7c8d7f365c5a66f3f4e4ef23ac1db06a126d..7a4c1a00a41f72fb401727b29deb3e6fd8840500 100644 --- a/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java +++ b/core/java/com/android/internal/dynamicanimation/animation/DynamicAnimation.java @@ -762,6 +762,10 @@ public abstract class DynamicAnimation> return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance(); } + public long getLastFrameTime() { + return mLastFrameTime; + } + /****************Sub class animations**************/ /** * Returns the acceleration at the given value with the given velocity. diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java index d61785e5f3e947456ecb8183d97c748b80c1a78c..07aa7206c0e7a411a575e2798c44c578de2cc202 100644 --- a/core/java/com/android/internal/os/BatteryStatsHistory.java +++ b/core/java/com/android/internal/os/BatteryStatsHistory.java @@ -83,7 +83,7 @@ public class BatteryStatsHistory { private static final String TAG = "BatteryStatsHistory"; // Current on-disk Parcel version. Must be updated when the format of the parcelable changes - private static final int VERSION = 210; + private static final int VERSION = 211; private static final String HISTORY_DIR = "battery-history"; private static final String FILE_SUFFIX = ".bh"; @@ -210,6 +210,8 @@ public class BatteryStatsHistory { private final MonotonicClock mMonotonicClock; // Monotonic time when we started writing to the history buffer private long mHistoryBufferStartTime; + // Monotonically increasing size of written history + private long mMonotonicHistorySize; private final ArraySet mWrittenPowerStatsDescriptors = new ArraySet<>(); private byte mLastHistoryStepLevel = 0; private boolean mMutable = true; @@ -909,6 +911,8 @@ public class BatteryStatsHistory { } // skip monotonic time field. p.readLong(); + // skip monotonic size field + p.readLong(); final int bufSize = p.readInt(); final int curPos = p.dataPosition(); @@ -964,6 +968,8 @@ public class BatteryStatsHistory { } // skip monotonic time field. out.readLong(); + // skip monotonic size field + out.readLong(); return true; } @@ -987,6 +993,7 @@ public class BatteryStatsHistory { p.setDataPosition(0); p.readInt(); // Skip the version field long monotonicTime = p.readLong(); + p.readLong(); // Skip monotonic size field p.setDataPosition(pos); return monotonicTime; } @@ -1819,6 +1826,7 @@ public class BatteryStatsHistory { // as long as no bit has changed both between now and the last entry, as // well as the last entry and the one before it (so we capture any toggles). if (DEBUG) Slog.i(TAG, "ADD: rewinding back to " + mHistoryBufferLastPos); + mMonotonicHistorySize -= (mHistoryBuffer.dataSize() - mHistoryBufferLastPos); mHistoryBuffer.setDataSize(mHistoryBufferLastPos); mHistoryBuffer.setDataPosition(mHistoryBufferLastPos); mHistoryBufferLastPos = -1; @@ -1934,6 +1942,7 @@ public class BatteryStatsHistory { } mHistoryLastWritten.tagsFirstOccurrence = hasTags; writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten); + mMonotonicHistorySize += (mHistoryBuffer.dataSize() - mHistoryBufferLastPos); cur.wakelockTag = null; cur.wakeReasonTag = null; cur.eventCode = HistoryItem.EVENT_NONE; @@ -2344,6 +2353,8 @@ public class BatteryStatsHistory { } mHistoryBufferStartTime = in.readLong(); + mMonotonicHistorySize = in.readLong(); + mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); @@ -2370,6 +2381,7 @@ public class BatteryStatsHistory { private void writeHistoryBuffer(Parcel out) { out.writeInt(BatteryStatsHistory.VERSION); out.writeLong(mHistoryBufferStartTime); + out.writeLong(mMonotonicHistorySize); out.writeInt(mHistoryBuffer.dataSize()); if (DEBUG) { Slog.i(TAG, "***************** WRITING HISTORY: " @@ -2456,6 +2468,14 @@ public class BatteryStatsHistory { } } + /** + * Returns the monotonically increasing size of written history, including the buffers + * that have already been discarded. + */ + public long getMonotonicHistorySize() { + return mMonotonicHistorySize; + } + /** * Prints battery stats history for debugging. */ diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java index f3dc896a765ef21f216ee9764d2d7214530c9d7b..a037cb421b0c081d74c4d32d86c662b785a7b1dc 100644 --- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java +++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java @@ -218,6 +218,22 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto // NOTE: Registering that datasource is an async operation, so there may be no data traced // for some messages logged right after the construction of this class. mDataSource.register(params); + + if (viewerConfigInputStreamProvider == null && viewerConfigFilePath != null) { + viewerConfigInputStreamProvider = new ViewerConfigInputStreamProvider() { + @NonNull + @Override + public ProtoInputStream getInputStream() { + try { + return new ProtoInputStream(new FileInputStream(viewerConfigFilePath)); + } catch (FileNotFoundException e) { + throw new RuntimeException( + "Failed to load viewer config file " + viewerConfigFilePath, e); + } + } + }; + } + this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider; this.mViewerConfigReader = viewerConfigReader; this.mCacheUpdater = cacheUpdater; diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java index 0a80e006d5bca7988f436c22a52e670879e75b27..571fe0ba37b237cb377956035799a5862adfe614 100644 --- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java +++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java @@ -39,7 +39,7 @@ public class ProtoLogViewerConfigReader { * or the viewer config is not loaded into memory. */ @Nullable - public synchronized String getViewerString(long messageHash) { + public String getViewerString(long messageHash) { return mLogMessageMap.get(messageHash); } @@ -96,6 +96,7 @@ public class ProtoLogViewerConfigReader { logger.log("Unloading viewer config hash " + hash); mLogMessageMap.remove(hash); } + mGroupHashes.remove(group); } } @@ -179,6 +180,6 @@ public class ProtoLogViewerConfigReader { } } - throw new RuntimeException("Group " + group + "not found in viewer config"); + throw new RuntimeException("Group " + group + " not found in viewer config"); } } diff --git a/core/java/com/android/internal/widget/NotificationProgressBar.java b/core/java/com/android/internal/widget/NotificationProgressBar.java index 3e597d73f217b198e5f4e7f22ea2644ecf6f621e..d3b1f972a955058d027838db2a36374d29bef810 100644 --- a/core/java/com/android/internal/widget/NotificationProgressBar.java +++ b/core/java/com/android/internal/widget/NotificationProgressBar.java @@ -20,16 +20,20 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification.ProgressStyle; import android.content.Context; +import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; +import android.graphics.drawable.LayerDrawable; import android.os.Bundle; import android.util.AttributeSet; +import android.util.Log; import android.view.RemotableViewMethod; import android.widget.ProgressBar; import android.widget.RemoteViews; import androidx.annotation.ColorInt; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import com.android.internal.widget.NotificationProgressDrawable.Part; @@ -49,7 +53,13 @@ import java.util.TreeSet; */ @RemoteViews.RemoteView public class NotificationProgressBar extends ProgressBar { + private static final String TAG = "NotificationProgressBar"; + private NotificationProgressModel mProgressModel; + + @Nullable + private List mProgressDrawableParts = null; + @Nullable private Drawable mProgressTrackerDrawable = null; @@ -58,7 +68,7 @@ public class NotificationProgressBar extends ProgressBar { } public NotificationProgressBar(Context context, AttributeSet attrs) { - this(context, attrs, com.android.internal.R.attr.progressBarStyle); + this(context, attrs, R.attr.progressBarStyle); } public NotificationProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { @@ -82,10 +92,42 @@ public class NotificationProgressBar extends ProgressBar { "Bundle shouldn't be null"); mProgressModel = NotificationProgressModel.fromBundle(bundle); + + if (mProgressModel.isIndeterminate()) { + final int indeterminateColor = mProgressModel.getIndeterminateColor(); + setIndeterminateTintList(ColorStateList.valueOf(indeterminateColor)); + } else { + mProgressDrawableParts = processAndConvertToDrawableParts(mProgressModel.getSegments(), + mProgressModel.getPoints(), + mProgressModel.getProgress(), mProgressModel.isStyledByProgress()); + + try { + final NotificationProgressDrawable drawable = getNotificationProgressDrawable(); + drawable.setParts(mProgressDrawableParts); + } catch (IllegalStateException ex) { + Log.e(TAG, "Can't set parts because can't get NotificationProgressDrawable", ex); + } + } } - private void setProgressModel(@NonNull NotificationProgressModel model) { - mProgressModel = model; + @NonNull + private NotificationProgressDrawable getNotificationProgressDrawable() { + final Drawable d = getProgressDrawable(); + if (d == null) { + throw new IllegalStateException("getProgressDrawable() returns null"); + } + if (!(d instanceof LayerDrawable)) { + throw new IllegalStateException("getProgressDrawable() doesn't return a LayerDrawable"); + } + + final Drawable layer = ((LayerDrawable) d).findDrawableByLayerId(R.id.background); + if (!(layer instanceof NotificationProgressDrawable)) { + throw new IllegalStateException( + "Couldn't get NotificationProgressDrawable, retrieved drawable is: " + ( + layer != null ? layer.toString() : null)); + } + + return (NotificationProgressDrawable) layer; } /** @@ -97,7 +139,6 @@ public class NotificationProgressBar extends ProgressBar { public void setProgressTrackerIcon(@Nullable Icon icon) { } - /** * Async version of {@link #setProgressTrackerIcon} */ diff --git a/core/java/com/android/internal/widget/NotificationProgressDrawable.java b/core/java/com/android/internal/widget/NotificationProgressDrawable.java index 89ef8759a169566d9bd19d0fc756de9057fae12b..2be7273e5d10d83e51e4241d640acc64aff1e56b 100644 --- a/core/java/com/android/internal/widget/NotificationProgressDrawable.java +++ b/core/java/com/android/internal/widget/NotificationProgressDrawable.java @@ -45,6 +45,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Objects; /** @@ -156,11 +157,18 @@ public final class NotificationProgressDrawable extends Drawable { } /** - * + * Set the segments and points that constitute the drawable. */ - public void setParts(@NonNull Part... parts) { + public void setParts(List parts) { mParts.clear(); - mParts.addAll(Arrays.asList(parts)); + mParts.addAll(parts); + } + + /** + * Set the segments and points that constitute the drawable. + */ + public void setParts(@NonNull Part... parts) { + setParts(Arrays.asList(parts)); } @Override @@ -379,7 +387,7 @@ public final class NotificationProgressDrawable extends Drawable { if (state.mThemeAttrsPoints != null) { final TypedArray a = t.resolveAttributes( state.mThemeAttrsPoints, R.styleable.NotificationProgressDrawablePoints); - updateSegmentsFromTypedArray(a); + updatePointsFromTypedArray(a); a.recycle(); } } @@ -651,9 +659,11 @@ public final class NotificationProgressDrawable extends Drawable { State(@NonNull State orig, @Nullable Resources res) { mChangingConfigurations = orig.mChangingConfigurations; + mSegSegGap = orig.mSegSegGap; + mSegPointGap = orig.mSegPointGap; + mStrokeWidth = orig.mStrokeWidth; mStrokeColor = orig.mStrokeColor; mFadedStrokeColor = orig.mFadedStrokeColor; - mStrokeWidth = orig.mStrokeWidth; mStrokeDashWidth = orig.mStrokeDashWidth; mStrokeDashGap = orig.mStrokeDashGap; mPointRadius = orig.mPointRadius; @@ -791,6 +801,7 @@ public final class NotificationProgressDrawable extends Drawable { final State state = mState; mStrokePaint.setStrokeWidth(state.mStrokeWidth); + mDashedStrokePaint.setStrokeWidth(state.mStrokeWidth); if (state.mStrokeDashWidth != 0.0f) { final DashPathEffect e = new DashPathEffect( diff --git a/core/java/com/android/internal/widget/NotificationRowIconView.java b/core/java/com/android/internal/widget/NotificationRowIconView.java index 98e6e8505534ce56d858c7fe2837dfbf874ef694..adcc0f64b598098c7fae4dbdd108e276ee23a20c 100644 --- a/core/java/com/android/internal/widget/NotificationRowIconView.java +++ b/core/java/com/android/internal/widget/NotificationRowIconView.java @@ -39,17 +39,24 @@ import com.android.internal.R; /** * An image view that holds the icon displayed at the start of a notification row. + * This can generally either display the "small icon" of a notification set via + * {@link this#setImageIcon(Icon)}, or an app icon controlled and fetched by the provider set + * through {@link this#setIconProvider(NotificationIconProvider)}. */ @RemoteViews.RemoteView public class NotificationRowIconView extends CachingIconView { + private NotificationIconProvider mIconProvider; + private boolean mApplyCircularCrop = false; private boolean mShouldShowAppIcon = false; + private Drawable mAppIcon = null; - // Padding and background set on the view prior to being changed by setShouldShowAppIcon(true), - // to be restored if shouldShowAppIcon becomes false again. + // Padding, background and colors set on the view prior to being overridden when showing the app + // icon, to be restored if we're showing the small icon again. private Rect mOriginalPadding = null; private Drawable mOriginalBackground = null; - + private int mOriginalBackgroundColor = ColoredIconHelper.COLOR_INVALID; + private int mOriginalIconColor = ColoredIconHelper.COLOR_INVALID; public NotificationRowIconView(Context context) { super(context); @@ -81,6 +88,71 @@ public class NotificationRowIconView extends CachingIconView { super.onFinishInflate(); } + /** + * Sets the icon provider for this view. This is used to determine whether we should show the + * app icon instead of the small icon, and to fetch the app icon if needed. + */ + public void setIconProvider(NotificationIconProvider iconProvider) { + mIconProvider = iconProvider; + } + + private Drawable loadAppIcon() { + if (mIconProvider != null && mIconProvider.shouldShowAppIcon()) { + return mIconProvider.getAppIcon(); + } + return null; + } + + @RemotableViewMethod(asyncImpl = "setImageIconAsync") + @Override + public void setImageIcon(Icon icon) { + if (Flags.notificationsRedesignAppIcons()) { + if (mAppIcon != null) { + // We already know that we should be using the app icon, and we already loaded it. + // We assume that cannot change throughout the lifetime of a notification, so + // there's nothing to do here. + return; + } + mAppIcon = loadAppIcon(); + if (mAppIcon != null) { + setImageDrawable(mAppIcon); + adjustViewForAppIcon(); + } else { + super.setImageIcon(icon); + restoreViewForSmallIcon(); + } + return; + } + super.setImageIcon(icon); + } + + @RemotableViewMethod + @Override + public Runnable setImageIconAsync(Icon icon) { + if (Flags.notificationsRedesignAppIcons()) { + if (mAppIcon != null) { + // We already know that we should be using the app icon, and we already loaded it. + // We assume that cannot change throughout the lifetime of a notification, so + // there's nothing to do here. + return () -> { + }; + } + mAppIcon = loadAppIcon(); + if (mAppIcon != null) { + return () -> { + setImageDrawable(mAppIcon); + adjustViewForAppIcon(); + }; + } else { + return () -> { + super.setImageIcon(icon); + restoreViewForSmallIcon(); + }; + } + } + return super.setImageIconAsync(icon); + } + /** Whether the icon represents the app icon (instead of the small icon). */ @RemotableViewMethod public void setShouldShowAppIcon(boolean shouldShowAppIcon) { @@ -91,35 +163,122 @@ public class NotificationRowIconView extends CachingIconView { mShouldShowAppIcon = shouldShowAppIcon; if (mShouldShowAppIcon) { - if (mOriginalPadding == null && mOriginalBackground == null) { - mOriginalPadding = new Rect(getPaddingLeft(), getPaddingTop(), - getPaddingRight(), getPaddingBottom()); - mOriginalBackground = getBackground(); - } - - setPadding(0, 0, 0, 0); - - // Make the background white in case the icon itself doesn't have one. - ColorFilter colorFilter = new PorterDuffColorFilter(Color.WHITE, - PorterDuff.Mode.SRC_ATOP); - - if (mOriginalBackground == null) { - setBackground(getContext().getDrawable(R.drawable.notification_icon_circle)); - } - getBackground().mutate().setColorFilter(colorFilter); + adjustViewForAppIcon(); } else { // Restore original padding and background if needed - if (mOriginalPadding != null) { - setPadding(mOriginalPadding.left, mOriginalPadding.top, mOriginalPadding.right, - mOriginalPadding.bottom); - mOriginalPadding = null; - } - setBackground(mOriginalBackground); - mOriginalBackground = null; + restoreViewForSmallIcon(); } } } + /** + * Override padding and background from the view to display the app icon. + */ + private void adjustViewForAppIcon() { + removePadding(); + + if (Flags.notificationsUseAppIconInRow()) { + addWhiteBackground(); + } else { + // No need to set the background for notification redesign, since the icon + // factory already does that for us. + removeBackground(); + } + } + + /** + * Restore padding and background overridden by {@link this#adjustViewForAppIcon}. + * Does nothing if they were not overridden. + */ + private void restoreViewForSmallIcon() { + restorePadding(); + restoreBackground(); + restoreColors(); + } + + private void removePadding() { + if (mOriginalPadding == null) { + mOriginalPadding = new Rect(getPaddingLeft(), getPaddingTop(), + getPaddingRight(), getPaddingBottom()); + } + setPadding(0, 0, 0, 0); + } + + private void restorePadding() { + if (mOriginalPadding != null) { + setPadding(mOriginalPadding.left, mOriginalPadding.top, + mOriginalPadding.right, + mOriginalPadding.bottom); + mOriginalPadding = null; + } + } + + private void removeBackground() { + if (mOriginalBackground == null) { + mOriginalBackground = getBackground(); + } + + setBackground(null); + } + + private void addWhiteBackground() { + if (mOriginalBackground == null) { + mOriginalBackground = getBackground(); + } + + // Make the background white in case the icon itself doesn't have one. + ColorFilter colorFilter = new PorterDuffColorFilter(Color.WHITE, + PorterDuff.Mode.SRC_ATOP); + + if (mOriginalBackground == null) { + setBackground(getContext().getDrawable(R.drawable.notification_icon_circle)); + } + getBackground().mutate().setColorFilter(colorFilter); + } + + private void restoreBackground() { + // NOTE: This will not work if the original background was null, but that's better than + // accidentally clearing the background. We expect that there's generally going to be one + // anyway unless we manually clear it. + if (mOriginalBackground != null) { + setBackground(mOriginalBackground); + mOriginalBackground = null; + } + } + + private void restoreColors() { + if (mOriginalBackgroundColor != ColoredIconHelper.COLOR_INVALID) { + super.setBackgroundColor(mOriginalBackgroundColor); + mOriginalBackgroundColor = ColoredIconHelper.COLOR_INVALID; + } + if (mOriginalIconColor != ColoredIconHelper.COLOR_INVALID) { + super.setOriginalIconColor(mOriginalIconColor); + mOriginalIconColor = ColoredIconHelper.COLOR_INVALID; + } + } + + @RemotableViewMethod + @Override + public void setBackgroundColor(int color) { + // Ignore color overrides if we're showing the app icon. + if (mAppIcon == null) { + super.setBackgroundColor(color); + } else { + mOriginalBackgroundColor = color; + } + } + + @RemotableViewMethod + @Override + public void setOriginalIconColor(int color) { + // Ignore color overrides if we're showing the app icon. + if (mAppIcon == null) { + super.setOriginalIconColor(color); + } else { + mOriginalIconColor = color; + } + } + @Nullable @Override Drawable loadSizeRestrictedIcon(@Nullable Icon icon) { @@ -197,4 +356,17 @@ public class NotificationRowIconView extends CachingIconView { return bitmap; } + + /** + * A provider that allows this view to verify whether it should use the app icon instead of the + * icon provided to it via setImageIcon, as well as actually fetching the app icon. It should + * primarily be called on the background thread. + */ + public interface NotificationIconProvider { + /** Whether this notification should use the app icon instead of the small icon. */ + boolean shouldShowAppIcon(); + + /** Get the app icon for this notification. */ + Drawable getAppIcon(); + } } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 2bc32657bd4a83fbf07727dfb8b479364461e270..816ace2310a57aecf5aa1a1cd85db2dd9bf8ded1 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -73,12 +73,6 @@ cc_library_shared_for_libandroid_runtime { srcs: [ "android_animation_PropertyValuesHolder.cpp", - "android_database_CursorWindow.cpp", - "android_database_SQLiteCommon.cpp", - "android_database_SQLiteConnection.cpp", - "android_database_SQLiteGlobal.cpp", - "android_database_SQLiteDebug.cpp", - "android_database_SQLiteRawStatement.cpp", "android_os_SystemClock.cpp", "android_os_SystemProperties.cpp", "android_os_Trace.cpp", @@ -163,6 +157,12 @@ cc_library_shared_for_libandroid_runtime { "android_opengl_GLES31.cpp", "android_opengl_GLES31Ext.cpp", "android_opengl_GLES32.cpp", + "android_database_CursorWindow.cpp", + "android_database_SQLiteCommon.cpp", + "android_database_SQLiteConnection.cpp", + "android_database_SQLiteGlobal.cpp", + "android_database_SQLiteDebug.cpp", + "android_database_SQLiteRawStatement.cpp", "android_graphics_GraphicBuffer.cpp", "android_graphics_SurfaceTexture.cpp", "android_view_CompositionSamplingListener.cpp", @@ -428,7 +428,6 @@ cc_library_shared_for_libandroid_runtime { "libnativehelper_jvm", "libpiex", "libpng", - "libsqlite", "libtiff_directory", "libui-types", "libutils", @@ -444,6 +443,12 @@ cc_library_shared_for_libandroid_runtime { host_linux: { srcs: [ "android_content_res_ApkAssets.cpp", + "android_database_CursorWindow.cpp", + "android_database_SQLiteCommon.cpp", + "android_database_SQLiteConnection.cpp", + "android_database_SQLiteGlobal.cpp", + "android_database_SQLiteDebug.cpp", + "android_database_SQLiteRawStatement.cpp", "android_hardware_input_InputApplicationHandle.cpp", "android_os_MessageQueue.cpp", "android_os_Parcel.cpp", @@ -459,6 +464,7 @@ cc_library_shared_for_libandroid_runtime { ], static_libs: [ "libbinderthreadstateutils", + "libsqlite", "libgui_window_info_static", ], shared_libs: [ diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp index 18c314610bb227e55652c5d14aaa9031588b84ed..c0e9215267e60341b56d66b15065544d69fc8e4e 100644 --- a/core/jni/android_database_CursorWindow.cpp +++ b/core/jni/android_database_CursorWindow.cpp @@ -38,9 +38,7 @@ #define LOG_NDEBUG 1 #include -#ifdef __linux__ #include "android_os_Parcel.h" -#endif #include "android_util_Binder.h" #include "android_database_SQLiteCommon.h" @@ -113,7 +111,6 @@ fail: return 0; } -#ifdef __linux__ static jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); @@ -131,7 +128,6 @@ static jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj window->getNumRows(), window->getNumColumns(), window); return reinterpret_cast(window); } -#endif static void nativeDispose(JNIEnv* env, jclass clazz, jlong windowPtr) { CursorWindow* window = reinterpret_cast(windowPtr); @@ -146,7 +142,6 @@ static jstring nativeGetName(JNIEnv* env, jclass clazz, jlong windowPtr) { return env->NewStringUTF(window->name().c_str()); } -#ifdef __linux__ static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jlong windowPtr, jobject parcelObj) { CursorWindow* window = reinterpret_cast(windowPtr); @@ -159,7 +154,6 @@ static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jlong windowPtr, jniThrowRuntimeException(env, msg.c_str()); } } -#endif static void nativeClear(JNIEnv * env, jclass clazz, jlong windowPtr) { CursorWindow* window = reinterpret_cast(windowPtr); @@ -526,35 +520,55 @@ static jboolean nativePutNull(JNIEnv* env, jclass clazz, jlong windowPtr, return true; } -static const JNINativeMethod sMethods[] = { - /* name, signature, funcPtr */ - {"nativeCreate", "(Ljava/lang/String;I)J", (void*)nativeCreate}, - {"nativeDispose", "(J)V", (void*)nativeDispose}, -#ifdef __linux__ - {"nativeCreateFromParcel", "(Landroid/os/Parcel;)J", (void*)nativeCreateFromParcel}, - {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel}, -#endif - {"nativeGetName", "(J)Ljava/lang/String;", (void*)nativeGetName}, - {"nativeGetBlob", "(JII)[B", (void*)nativeGetBlob}, - {"nativeGetString", "(JII)Ljava/lang/String;", (void*)nativeGetString}, - {"nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V", - (void*)nativeCopyStringToBuffer}, - {"nativePutBlob", "(J[BII)Z", (void*)nativePutBlob}, - {"nativePutString", "(JLjava/lang/String;II)Z", (void*)nativePutString}, - - // ------- @FastNative below here ---------------------- - {"nativeClear", "(J)V", (void*)nativeClear}, - {"nativeGetNumRows", "(J)I", (void*)nativeGetNumRows}, - {"nativeSetNumColumns", "(JI)Z", (void*)nativeSetNumColumns}, - {"nativeAllocRow", "(J)Z", (void*)nativeAllocRow}, - {"nativeFreeLastRow", "(J)V", (void*)nativeFreeLastRow}, - {"nativeGetType", "(JII)I", (void*)nativeGetType}, - {"nativeGetLong", "(JII)J", (void*)nativeGetLong}, - {"nativeGetDouble", "(JII)D", (void*)nativeGetDouble}, - - {"nativePutLong", "(JJII)Z", (void*)nativePutLong}, - {"nativePutDouble", "(JDII)Z", (void*)nativePutDouble}, - {"nativePutNull", "(JII)Z", (void*)nativePutNull}, +static const JNINativeMethod sMethods[] = +{ + /* name, signature, funcPtr */ + { "nativeCreate", "(Ljava/lang/String;I)J", + (void*)nativeCreate }, + { "nativeCreateFromParcel", "(Landroid/os/Parcel;)J", + (void*)nativeCreateFromParcel }, + { "nativeDispose", "(J)V", + (void*)nativeDispose }, + { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V", + (void*)nativeWriteToParcel }, + + { "nativeGetName", "(J)Ljava/lang/String;", + (void*)nativeGetName }, + { "nativeGetBlob", "(JII)[B", + (void*)nativeGetBlob }, + { "nativeGetString", "(JII)Ljava/lang/String;", + (void*)nativeGetString }, + { "nativeCopyStringToBuffer", "(JIILandroid/database/CharArrayBuffer;)V", + (void*)nativeCopyStringToBuffer }, + { "nativePutBlob", "(J[BII)Z", + (void*)nativePutBlob }, + { "nativePutString", "(JLjava/lang/String;II)Z", + (void*)nativePutString }, + + // ------- @FastNative below here ---------------------- + { "nativeClear", "(J)V", + (void*)nativeClear }, + { "nativeGetNumRows", "(J)I", + (void*)nativeGetNumRows }, + { "nativeSetNumColumns", "(JI)Z", + (void*)nativeSetNumColumns }, + { "nativeAllocRow", "(J)Z", + (void*)nativeAllocRow }, + { "nativeFreeLastRow", "(J)V", + (void*)nativeFreeLastRow }, + { "nativeGetType", "(JII)I", + (void*)nativeGetType }, + { "nativeGetLong", "(JII)J", + (void*)nativeGetLong }, + { "nativeGetDouble", "(JII)D", + (void*)nativeGetDouble }, + + { "nativePutLong", "(JJII)Z", + (void*)nativePutLong }, + { "nativePutDouble", "(JDII)Z", + (void*)nativePutDouble }, + { "nativePutNull", "(JII)Z", + (void*)nativePutNull }, }; int register_android_database_CursorWindow(JNIEnv* env) diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp index 041fed74c57397cc8e83b82c7284b3606e3ec1a0..a0987373687b97d83a5484729c34b8c79c165d85 100644 --- a/core/jni/android_hardware_camera2_CameraMetadata.cpp +++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp @@ -336,7 +336,7 @@ static void CameraMetadata_swap(JNIEnv *env, jclass thiz, jlong ptr, jlong other static jbyteArray CameraMetadata_readValues(JNIEnv *env, jclass thiz, jint tag, jlong ptr) { ALOGV("%s (tag = %d)", __FUNCTION__, tag); - CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, ptr); + const CameraMetadata *metadata = CameraMetadata_getPointerThrow(env, ptr); if (metadata == NULL) return NULL; const camera_metadata_t *metaBuffer = metadata->getAndLock(); @@ -349,16 +349,15 @@ static jbyteArray CameraMetadata_readValues(JNIEnv *env, jclass thiz, jint tag, } size_t tagSize = Helpers::getTypeSize(tagType); - camera_metadata_entry entry = metadata->find(tag); + camera_metadata_ro_entry entry = metadata->find(tag); if (entry.count == 0) { - if (!metadata->exists(tag)) { - ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag); - return NULL; - } else { - // OK: we will return a 0-sized array. - ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__, - tag); - } + if (!metadata->exists(tag)) { + ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag); + return NULL; + } else { + // OK: we will return a 0-sized array. + ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__, tag); + } } jsize byteCount = entry.count * tagSize; diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 9bccf5af709670bed1c2de37b5fb39b83da0999d..8eaa7aa99a2da9553a989f6c1dfb64989e4a1f2a 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -747,16 +747,12 @@ android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint strea indexMax)); } -static jint -android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, - jobject thiz, - jint stream, - jint index, - jint device) -{ +static jint android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream, + jint index, jboolean muted, + jint device) { return check_AudioSystem_Command( AudioSystem::setStreamVolumeIndex(static_cast(stream), index, - static_cast(device))); + muted, static_cast(device))); } static jint @@ -773,13 +769,9 @@ android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env, return index; } -static jint -android_media_AudioSystem_setVolumeIndexForAttributes(JNIEnv *env, - jobject thiz, - jobject jaa, - jint index, - jint device) -{ +static jint android_media_AudioSystem_setVolumeIndexForAttributes(JNIEnv *env, jobject thiz, + jobject jaa, jint index, + jboolean muted, jint device) { // read the AudioAttributes values JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique(); jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get()); @@ -787,7 +779,7 @@ android_media_AudioSystem_setVolumeIndexForAttributes(JNIEnv *env, return jStatus; } return check_AudioSystem_Command( - AudioSystem::setVolumeIndexForAttributes(*(paa.get()), index, + AudioSystem::setVolumeIndexForAttributes(*(paa.get()), index, muted, static_cast(device))); } @@ -3448,182 +3440,179 @@ static void android_media_AudioSystem_triggerSystemPropertyUpdate(JNIEnv *env, #define MAKE_AUDIO_SYSTEM_METHOD(x) \ MAKE_JNI_NATIVE_METHOD_AUTOSIG(#x, android_media_AudioSystem_##x) -static const JNINativeMethod gMethods[] = - {MAKE_AUDIO_SYSTEM_METHOD(setParameters), - MAKE_AUDIO_SYSTEM_METHOD(getParameters), - MAKE_AUDIO_SYSTEM_METHOD(muteMicrophone), - MAKE_AUDIO_SYSTEM_METHOD(isMicrophoneMuted), - MAKE_AUDIO_SYSTEM_METHOD(isStreamActive), - MAKE_AUDIO_SYSTEM_METHOD(isStreamActiveRemotely), - MAKE_AUDIO_SYSTEM_METHOD(isSourceActive), - MAKE_AUDIO_SYSTEM_METHOD(newAudioSessionId), - MAKE_AUDIO_SYSTEM_METHOD(newAudioPlayerId), - MAKE_AUDIO_SYSTEM_METHOD(newAudioRecorderId), - MAKE_JNI_NATIVE_METHOD("setDeviceConnectionState", "(ILandroid/os/Parcel;I)I", - android_media_AudioSystem_setDeviceConnectionState), - MAKE_AUDIO_SYSTEM_METHOD(getDeviceConnectionState), - MAKE_AUDIO_SYSTEM_METHOD(handleDeviceConfigChange), - MAKE_AUDIO_SYSTEM_METHOD(setPhoneState), - MAKE_AUDIO_SYSTEM_METHOD(setForceUse), - MAKE_AUDIO_SYSTEM_METHOD(getForceUse), - MAKE_AUDIO_SYSTEM_METHOD(setDeviceAbsoluteVolumeEnabled), - MAKE_AUDIO_SYSTEM_METHOD(initStreamVolume), - MAKE_AUDIO_SYSTEM_METHOD(setStreamVolumeIndex), - MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeIndex), - MAKE_JNI_NATIVE_METHOD("setVolumeIndexForAttributes", - "(Landroid/media/AudioAttributes;II)I", - android_media_AudioSystem_setVolumeIndexForAttributes), - MAKE_JNI_NATIVE_METHOD("getVolumeIndexForAttributes", - "(Landroid/media/AudioAttributes;I)I", - android_media_AudioSystem_getVolumeIndexForAttributes), - MAKE_JNI_NATIVE_METHOD("getMinVolumeIndexForAttributes", - "(Landroid/media/AudioAttributes;)I", - android_media_AudioSystem_getMinVolumeIndexForAttributes), - MAKE_JNI_NATIVE_METHOD("getMaxVolumeIndexForAttributes", - "(Landroid/media/AudioAttributes;)I", - android_media_AudioSystem_getMaxVolumeIndexForAttributes), - MAKE_AUDIO_SYSTEM_METHOD(setMasterVolume), - MAKE_AUDIO_SYSTEM_METHOD(getMasterVolume), - MAKE_AUDIO_SYSTEM_METHOD(setMasterMute), - MAKE_AUDIO_SYSTEM_METHOD(getMasterMute), - MAKE_AUDIO_SYSTEM_METHOD(setMasterMono), - MAKE_AUDIO_SYSTEM_METHOD(getMasterMono), - MAKE_AUDIO_SYSTEM_METHOD(setMasterBalance), - MAKE_AUDIO_SYSTEM_METHOD(getMasterBalance), - MAKE_AUDIO_SYSTEM_METHOD(getPrimaryOutputSamplingRate), - MAKE_AUDIO_SYSTEM_METHOD(getPrimaryOutputFrameCount), - MAKE_AUDIO_SYSTEM_METHOD(getOutputLatency), - MAKE_AUDIO_SYSTEM_METHOD(setLowRamDevice), - MAKE_AUDIO_SYSTEM_METHOD(checkAudioFlinger), - MAKE_JNI_NATIVE_METHOD("setAudioFlingerBinder", "(Landroid/os/IBinder;)V", - android_media_AudioSystem_setAudioFlingerBinder), - MAKE_JNI_NATIVE_METHOD("listAudioPorts", "(Ljava/util/ArrayList;[I)I", - android_media_AudioSystem_listAudioPorts), - MAKE_JNI_NATIVE_METHOD("getSupportedDeviceTypes", "(ILandroid/util/IntArray;)I", - android_media_AudioSystem_getSupportedDeviceTypes), - MAKE_JNI_NATIVE_METHOD("createAudioPatch", - "([Landroid/media/AudioPatch;[Landroid/media/" - "AudioPortConfig;[Landroid/media/AudioPortConfig;)I", - android_media_AudioSystem_createAudioPatch), - MAKE_JNI_NATIVE_METHOD("releaseAudioPatch", "(Landroid/media/AudioPatch;)I", - android_media_AudioSystem_releaseAudioPatch), - MAKE_JNI_NATIVE_METHOD("listAudioPatches", "(Ljava/util/ArrayList;[I)I", - android_media_AudioSystem_listAudioPatches), - MAKE_JNI_NATIVE_METHOD("setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I", - android_media_AudioSystem_setAudioPortConfig), - MAKE_JNI_NATIVE_METHOD("startAudioSource", - "(Landroid/media/AudioPortConfig;Landroid/media/AudioAttributes;)I", - android_media_AudioSystem_startAudioSource), - MAKE_AUDIO_SYSTEM_METHOD(stopAudioSource), - MAKE_AUDIO_SYSTEM_METHOD(getAudioHwSyncForSession), - MAKE_JNI_NATIVE_METHOD("registerPolicyMixes", "(Ljava/util/ArrayList;Z)I", - android_media_AudioSystem_registerPolicyMixes), - MAKE_JNI_NATIVE_METHOD("getRegisteredPolicyMixes", "(Ljava/util/List;)I", - android_media_AudioSystem_getRegisteredPolicyMixes), - MAKE_JNI_NATIVE_METHOD("updatePolicyMixes", - "([Landroid/media/audiopolicy/AudioMix;[Landroid/media/audiopolicy/" - "AudioMixingRule;)I", - android_media_AudioSystem_updatePolicyMixes), - MAKE_JNI_NATIVE_METHOD("setUidDeviceAffinities", "(I[I[Ljava/lang/String;)I", - android_media_AudioSystem_setUidDeviceAffinities), - MAKE_AUDIO_SYSTEM_METHOD(removeUidDeviceAffinities), - MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_dynamic_policy_callback", - android_media_AudioSystem_registerDynPolicyCallback), - MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_recording_callback", - android_media_AudioSystem_registerRecordingCallback), - MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_routing_callback", - android_media_AudioSystem_registerRoutingCallback), - MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_vol_range_init_req_callback", - android_media_AudioSystem_registerVolRangeInitReqCallback), - MAKE_AUDIO_SYSTEM_METHOD(systemReady), - MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeDB), - MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_get_offload_support", - android_media_AudioSystem_getOffloadSupport), - MAKE_JNI_NATIVE_METHOD("getMicrophones", "(Ljava/util/ArrayList;)I", - android_media_AudioSystem_getMicrophones), - MAKE_JNI_NATIVE_METHOD("getSurroundFormats", "(Ljava/util/Map;)I", - android_media_AudioSystem_getSurroundFormats), - MAKE_JNI_NATIVE_METHOD("getReportedSurroundFormats", "(Ljava/util/ArrayList;)I", - android_media_AudioSystem_getReportedSurroundFormats), - MAKE_AUDIO_SYSTEM_METHOD(setSurroundFormatEnabled), - MAKE_AUDIO_SYSTEM_METHOD(setAssistantServicesUids), - MAKE_AUDIO_SYSTEM_METHOD(setActiveAssistantServicesUids), - MAKE_AUDIO_SYSTEM_METHOD(setA11yServicesUids), - MAKE_AUDIO_SYSTEM_METHOD(isHapticPlaybackSupported), - MAKE_AUDIO_SYSTEM_METHOD(isUltrasoundSupported), - MAKE_JNI_NATIVE_METHOD( - "getHwOffloadFormatsSupportedForBluetoothMedia", "(ILjava/util/ArrayList;)I", - android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia), - MAKE_AUDIO_SYSTEM_METHOD(setSupportedSystemUsages), - MAKE_AUDIO_SYSTEM_METHOD(setAllowedCapturePolicy), - MAKE_AUDIO_SYSTEM_METHOD(setRttEnabled), - MAKE_AUDIO_SYSTEM_METHOD(setAudioHalPids), - MAKE_AUDIO_SYSTEM_METHOD(isCallScreeningModeSupported), - MAKE_JNI_NATIVE_METHOD("setDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I", - android_media_AudioSystem_setDevicesRoleForStrategy), - MAKE_JNI_NATIVE_METHOD("removeDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I", - android_media_AudioSystem_removeDevicesRoleForStrategy), - MAKE_AUDIO_SYSTEM_METHOD(clearDevicesRoleForStrategy), - MAKE_JNI_NATIVE_METHOD("getDevicesForRoleAndStrategy", "(IILjava/util/List;)I", - android_media_AudioSystem_getDevicesForRoleAndStrategy), - MAKE_JNI_NATIVE_METHOD("setDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", - android_media_AudioSystem_setDevicesRoleForCapturePreset), - MAKE_JNI_NATIVE_METHOD("addDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", - android_media_AudioSystem_addDevicesRoleForCapturePreset), - MAKE_JNI_NATIVE_METHOD("removeDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", - android_media_AudioSystem_removeDevicesRoleForCapturePreset), - MAKE_AUDIO_SYSTEM_METHOD(clearDevicesRoleForCapturePreset), - MAKE_JNI_NATIVE_METHOD("getDevicesForRoleAndCapturePreset", "(IILjava/util/List;)I", - android_media_AudioSystem_getDevicesForRoleAndCapturePreset), - MAKE_JNI_NATIVE_METHOD("getDevicesForAttributes", - "(Landroid/media/AudioAttributes;[Landroid/media/" - "AudioDeviceAttributes;Z)I", - android_media_AudioSystem_getDevicesForAttributes), - MAKE_JNI_NATIVE_METHOD("setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I", - android_media_AudioSystem_setUserIdDeviceAffinities), - MAKE_AUDIO_SYSTEM_METHOD(removeUserIdDeviceAffinities), - MAKE_AUDIO_SYSTEM_METHOD(setCurrentImeUid), - MAKE_JNI_NATIVE_METHOD("setVibratorInfos", "(Ljava/util/List;)I", - android_media_AudioSystem_setVibratorInfos), - MAKE_JNI_NATIVE_METHOD("nativeGetSpatializer", - "(Landroid/media/INativeSpatializerCallback;)Landroid/os/IBinder;", - android_media_AudioSystem_getSpatializer), - MAKE_JNI_NATIVE_METHOD("canBeSpatialized", - "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;" - "[Landroid/media/AudioDeviceAttributes;)Z", - android_media_AudioSystem_canBeSpatialized), - MAKE_JNI_NATIVE_METHOD("nativeGetSoundDose", - "(Landroid/media/ISoundDoseCallback;)Landroid/os/IBinder;", - android_media_AudioSystem_nativeGetSoundDose), - MAKE_JNI_NATIVE_METHOD("getDirectPlaybackSupport", - "(Landroid/media/AudioFormat;Landroid/media/AudioAttributes;)I", - android_media_AudioSystem_getDirectPlaybackSupport), - MAKE_JNI_NATIVE_METHOD("getDirectProfilesForAttributes", - "(Landroid/media/AudioAttributes;Ljava/util/ArrayList;)I", - android_media_AudioSystem_getDirectProfilesForAttributes), - MAKE_JNI_NATIVE_METHOD("getSupportedMixerAttributes", "(ILjava/util/List;)I", - android_media_AudioSystem_getSupportedMixerAttributes), - MAKE_JNI_NATIVE_METHOD("setPreferredMixerAttributes", - "(Landroid/media/AudioAttributes;IILandroid/media/" - "AudioMixerAttributes;)I", - android_media_AudioSystem_setPreferredMixerAttributes), - MAKE_JNI_NATIVE_METHOD("getPreferredMixerAttributes", - "(Landroid/media/AudioAttributes;ILjava/util/List;)I", - android_media_AudioSystem_getPreferredMixerAttributes), - MAKE_JNI_NATIVE_METHOD("clearPreferredMixerAttributes", - "(Landroid/media/AudioAttributes;II)I", - android_media_AudioSystem_clearPreferredMixerAttributes), - MAKE_AUDIO_SYSTEM_METHOD(supportsBluetoothVariableLatency), - MAKE_AUDIO_SYSTEM_METHOD(setBluetoothVariableLatencyEnabled), - MAKE_AUDIO_SYSTEM_METHOD(isBluetoothVariableLatencyEnabled), - MAKE_JNI_NATIVE_METHOD("listenForSystemPropertyChange", - "(Ljava/lang/String;Ljava/lang/Runnable;)J", - android_media_AudioSystem_listenForSystemPropertyChange), - MAKE_JNI_NATIVE_METHOD("triggerSystemPropertyUpdate", - "(J)V", - android_media_AudioSystem_triggerSystemPropertyUpdate), - - }; +static const JNINativeMethod gMethods[] = { + MAKE_AUDIO_SYSTEM_METHOD(setParameters), + MAKE_AUDIO_SYSTEM_METHOD(getParameters), + MAKE_AUDIO_SYSTEM_METHOD(muteMicrophone), + MAKE_AUDIO_SYSTEM_METHOD(isMicrophoneMuted), + MAKE_AUDIO_SYSTEM_METHOD(isStreamActive), + MAKE_AUDIO_SYSTEM_METHOD(isStreamActiveRemotely), + MAKE_AUDIO_SYSTEM_METHOD(isSourceActive), + MAKE_AUDIO_SYSTEM_METHOD(newAudioSessionId), + MAKE_AUDIO_SYSTEM_METHOD(newAudioPlayerId), + MAKE_AUDIO_SYSTEM_METHOD(newAudioRecorderId), + MAKE_JNI_NATIVE_METHOD("setDeviceConnectionState", "(ILandroid/os/Parcel;I)I", + android_media_AudioSystem_setDeviceConnectionState), + MAKE_AUDIO_SYSTEM_METHOD(getDeviceConnectionState), + MAKE_AUDIO_SYSTEM_METHOD(handleDeviceConfigChange), + MAKE_AUDIO_SYSTEM_METHOD(setPhoneState), + MAKE_AUDIO_SYSTEM_METHOD(setForceUse), + MAKE_AUDIO_SYSTEM_METHOD(getForceUse), + MAKE_AUDIO_SYSTEM_METHOD(setDeviceAbsoluteVolumeEnabled), + MAKE_AUDIO_SYSTEM_METHOD(initStreamVolume), + MAKE_AUDIO_SYSTEM_METHOD(setStreamVolumeIndex), + MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeIndex), + MAKE_JNI_NATIVE_METHOD("setVolumeIndexForAttributes", + "(Landroid/media/AudioAttributes;IZI)I", + android_media_AudioSystem_setVolumeIndexForAttributes), + MAKE_JNI_NATIVE_METHOD("getVolumeIndexForAttributes", "(Landroid/media/AudioAttributes;I)I", + android_media_AudioSystem_getVolumeIndexForAttributes), + MAKE_JNI_NATIVE_METHOD("getMinVolumeIndexForAttributes", + "(Landroid/media/AudioAttributes;)I", + android_media_AudioSystem_getMinVolumeIndexForAttributes), + MAKE_JNI_NATIVE_METHOD("getMaxVolumeIndexForAttributes", + "(Landroid/media/AudioAttributes;)I", + android_media_AudioSystem_getMaxVolumeIndexForAttributes), + MAKE_AUDIO_SYSTEM_METHOD(setMasterVolume), + MAKE_AUDIO_SYSTEM_METHOD(getMasterVolume), + MAKE_AUDIO_SYSTEM_METHOD(setMasterMute), + MAKE_AUDIO_SYSTEM_METHOD(getMasterMute), + MAKE_AUDIO_SYSTEM_METHOD(setMasterMono), + MAKE_AUDIO_SYSTEM_METHOD(getMasterMono), + MAKE_AUDIO_SYSTEM_METHOD(setMasterBalance), + MAKE_AUDIO_SYSTEM_METHOD(getMasterBalance), + MAKE_AUDIO_SYSTEM_METHOD(getPrimaryOutputSamplingRate), + MAKE_AUDIO_SYSTEM_METHOD(getPrimaryOutputFrameCount), + MAKE_AUDIO_SYSTEM_METHOD(getOutputLatency), + MAKE_AUDIO_SYSTEM_METHOD(setLowRamDevice), + MAKE_AUDIO_SYSTEM_METHOD(checkAudioFlinger), + MAKE_JNI_NATIVE_METHOD("setAudioFlingerBinder", "(Landroid/os/IBinder;)V", + android_media_AudioSystem_setAudioFlingerBinder), + MAKE_JNI_NATIVE_METHOD("listAudioPorts", "(Ljava/util/ArrayList;[I)I", + android_media_AudioSystem_listAudioPorts), + MAKE_JNI_NATIVE_METHOD("getSupportedDeviceTypes", "(ILandroid/util/IntArray;)I", + android_media_AudioSystem_getSupportedDeviceTypes), + MAKE_JNI_NATIVE_METHOD("createAudioPatch", + "([Landroid/media/AudioPatch;[Landroid/media/" + "AudioPortConfig;[Landroid/media/AudioPortConfig;)I", + android_media_AudioSystem_createAudioPatch), + MAKE_JNI_NATIVE_METHOD("releaseAudioPatch", "(Landroid/media/AudioPatch;)I", + android_media_AudioSystem_releaseAudioPatch), + MAKE_JNI_NATIVE_METHOD("listAudioPatches", "(Ljava/util/ArrayList;[I)I", + android_media_AudioSystem_listAudioPatches), + MAKE_JNI_NATIVE_METHOD("setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I", + android_media_AudioSystem_setAudioPortConfig), + MAKE_JNI_NATIVE_METHOD("startAudioSource", + "(Landroid/media/AudioPortConfig;Landroid/media/AudioAttributes;)I", + android_media_AudioSystem_startAudioSource), + MAKE_AUDIO_SYSTEM_METHOD(stopAudioSource), + MAKE_AUDIO_SYSTEM_METHOD(getAudioHwSyncForSession), + MAKE_JNI_NATIVE_METHOD("registerPolicyMixes", "(Ljava/util/ArrayList;Z)I", + android_media_AudioSystem_registerPolicyMixes), + MAKE_JNI_NATIVE_METHOD("getRegisteredPolicyMixes", "(Ljava/util/List;)I", + android_media_AudioSystem_getRegisteredPolicyMixes), + MAKE_JNI_NATIVE_METHOD("updatePolicyMixes", + "([Landroid/media/audiopolicy/AudioMix;[Landroid/media/audiopolicy/" + "AudioMixingRule;)I", + android_media_AudioSystem_updatePolicyMixes), + MAKE_JNI_NATIVE_METHOD("setUidDeviceAffinities", "(I[I[Ljava/lang/String;)I", + android_media_AudioSystem_setUidDeviceAffinities), + MAKE_AUDIO_SYSTEM_METHOD(removeUidDeviceAffinities), + MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_dynamic_policy_callback", + android_media_AudioSystem_registerDynPolicyCallback), + MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_recording_callback", + android_media_AudioSystem_registerRecordingCallback), + MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_routing_callback", + android_media_AudioSystem_registerRoutingCallback), + MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_vol_range_init_req_callback", + android_media_AudioSystem_registerVolRangeInitReqCallback), + MAKE_AUDIO_SYSTEM_METHOD(systemReady), + MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeDB), + MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_get_offload_support", + android_media_AudioSystem_getOffloadSupport), + MAKE_JNI_NATIVE_METHOD("getMicrophones", "(Ljava/util/ArrayList;)I", + android_media_AudioSystem_getMicrophones), + MAKE_JNI_NATIVE_METHOD("getSurroundFormats", "(Ljava/util/Map;)I", + android_media_AudioSystem_getSurroundFormats), + MAKE_JNI_NATIVE_METHOD("getReportedSurroundFormats", "(Ljava/util/ArrayList;)I", + android_media_AudioSystem_getReportedSurroundFormats), + MAKE_AUDIO_SYSTEM_METHOD(setSurroundFormatEnabled), + MAKE_AUDIO_SYSTEM_METHOD(setAssistantServicesUids), + MAKE_AUDIO_SYSTEM_METHOD(setActiveAssistantServicesUids), + MAKE_AUDIO_SYSTEM_METHOD(setA11yServicesUids), + MAKE_AUDIO_SYSTEM_METHOD(isHapticPlaybackSupported), + MAKE_AUDIO_SYSTEM_METHOD(isUltrasoundSupported), + MAKE_JNI_NATIVE_METHOD( + "getHwOffloadFormatsSupportedForBluetoothMedia", "(ILjava/util/ArrayList;)I", + android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia), + MAKE_AUDIO_SYSTEM_METHOD(setSupportedSystemUsages), + MAKE_AUDIO_SYSTEM_METHOD(setAllowedCapturePolicy), + MAKE_AUDIO_SYSTEM_METHOD(setRttEnabled), + MAKE_AUDIO_SYSTEM_METHOD(setAudioHalPids), + MAKE_AUDIO_SYSTEM_METHOD(isCallScreeningModeSupported), + MAKE_JNI_NATIVE_METHOD("setDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I", + android_media_AudioSystem_setDevicesRoleForStrategy), + MAKE_JNI_NATIVE_METHOD("removeDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I", + android_media_AudioSystem_removeDevicesRoleForStrategy), + MAKE_AUDIO_SYSTEM_METHOD(clearDevicesRoleForStrategy), + MAKE_JNI_NATIVE_METHOD("getDevicesForRoleAndStrategy", "(IILjava/util/List;)I", + android_media_AudioSystem_getDevicesForRoleAndStrategy), + MAKE_JNI_NATIVE_METHOD("setDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", + android_media_AudioSystem_setDevicesRoleForCapturePreset), + MAKE_JNI_NATIVE_METHOD("addDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", + android_media_AudioSystem_addDevicesRoleForCapturePreset), + MAKE_JNI_NATIVE_METHOD("removeDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", + android_media_AudioSystem_removeDevicesRoleForCapturePreset), + MAKE_AUDIO_SYSTEM_METHOD(clearDevicesRoleForCapturePreset), + MAKE_JNI_NATIVE_METHOD("getDevicesForRoleAndCapturePreset", "(IILjava/util/List;)I", + android_media_AudioSystem_getDevicesForRoleAndCapturePreset), + MAKE_JNI_NATIVE_METHOD("getDevicesForAttributes", + "(Landroid/media/AudioAttributes;[Landroid/media/" + "AudioDeviceAttributes;Z)I", + android_media_AudioSystem_getDevicesForAttributes), + MAKE_JNI_NATIVE_METHOD("setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I", + android_media_AudioSystem_setUserIdDeviceAffinities), + MAKE_AUDIO_SYSTEM_METHOD(removeUserIdDeviceAffinities), + MAKE_AUDIO_SYSTEM_METHOD(setCurrentImeUid), + MAKE_JNI_NATIVE_METHOD("setVibratorInfos", "(Ljava/util/List;)I", + android_media_AudioSystem_setVibratorInfos), + MAKE_JNI_NATIVE_METHOD("nativeGetSpatializer", + "(Landroid/media/INativeSpatializerCallback;)Landroid/os/IBinder;", + android_media_AudioSystem_getSpatializer), + MAKE_JNI_NATIVE_METHOD("canBeSpatialized", + "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;" + "[Landroid/media/AudioDeviceAttributes;)Z", + android_media_AudioSystem_canBeSpatialized), + MAKE_JNI_NATIVE_METHOD("nativeGetSoundDose", + "(Landroid/media/ISoundDoseCallback;)Landroid/os/IBinder;", + android_media_AudioSystem_nativeGetSoundDose), + MAKE_JNI_NATIVE_METHOD("getDirectPlaybackSupport", + "(Landroid/media/AudioFormat;Landroid/media/AudioAttributes;)I", + android_media_AudioSystem_getDirectPlaybackSupport), + MAKE_JNI_NATIVE_METHOD("getDirectProfilesForAttributes", + "(Landroid/media/AudioAttributes;Ljava/util/ArrayList;)I", + android_media_AudioSystem_getDirectProfilesForAttributes), + MAKE_JNI_NATIVE_METHOD("getSupportedMixerAttributes", "(ILjava/util/List;)I", + android_media_AudioSystem_getSupportedMixerAttributes), + MAKE_JNI_NATIVE_METHOD("setPreferredMixerAttributes", + "(Landroid/media/AudioAttributes;IILandroid/media/" + "AudioMixerAttributes;)I", + android_media_AudioSystem_setPreferredMixerAttributes), + MAKE_JNI_NATIVE_METHOD("getPreferredMixerAttributes", + "(Landroid/media/AudioAttributes;ILjava/util/List;)I", + android_media_AudioSystem_getPreferredMixerAttributes), + MAKE_JNI_NATIVE_METHOD("clearPreferredMixerAttributes", + "(Landroid/media/AudioAttributes;II)I", + android_media_AudioSystem_clearPreferredMixerAttributes), + MAKE_AUDIO_SYSTEM_METHOD(supportsBluetoothVariableLatency), + MAKE_AUDIO_SYSTEM_METHOD(setBluetoothVariableLatencyEnabled), + MAKE_AUDIO_SYSTEM_METHOD(isBluetoothVariableLatencyEnabled), + MAKE_JNI_NATIVE_METHOD("listenForSystemPropertyChange", + "(Ljava/lang/String;Ljava/lang/Runnable;)J", + android_media_AudioSystem_listenForSystemPropertyChange), + MAKE_JNI_NATIVE_METHOD("triggerSystemPropertyUpdate", "(J)V", + android_media_AudioSystem_triggerSystemPropertyUpdate), +}; static const JNINativeMethod gEventHandlerMethods[] = {MAKE_JNI_NATIVE_METHOD("native_setup", "(Ljava/lang/Object;)V", diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp index f5992d9063231a809c22963e2ddea39c6725ea02..ce40e51bee99d5c38c189ceec3c930125bf7510a 100644 --- a/core/jni/android_view_InputDevice.cpp +++ b/core/jni/android_view_InputDevice.cpp @@ -60,7 +60,7 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi ? layoutInfo->layoutType.c_str() : NULL)); - std::shared_ptr map = deviceInfo.getKeyCharacterMap(); + const KeyCharacterMap* map = deviceInfo.getKeyCharacterMap(); std::unique_ptr mapCopy; if (map != nullptr) { mapCopy = std::make_unique(*map); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index a939d9274956bcc1f557c246d6478bbb1885a77f..755704a5ad9126f22f1d3e1702fc92f0539ad4e2 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -115,6 +115,7 @@ static struct { jfieldID supportedDisplayModes; jfieldID activeDisplayModeId; jfieldID renderFrameRate; + jfieldID hasArrSupport; jfieldID supportedColorModes; jfieldID activeColorMode; jfieldID hdrCapabilities; @@ -1453,7 +1454,7 @@ static jobject nativeGetDynamicDisplayInfo(JNIEnv* env, jclass clazz, jlong disp env->SetIntField(object, gDynamicDisplayInfoClassInfo.activeDisplayModeId, info.activeDisplayModeId); env->SetFloatField(object, gDynamicDisplayInfoClassInfo.renderFrameRate, info.renderFrameRate); - + env->SetBooleanField(object, gDynamicDisplayInfoClassInfo.hasArrSupport, info.hasArrSupport); jintArray colorModesArray = env->NewIntArray(info.supportedColorModes.size()); if (colorModesArray == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); @@ -2641,6 +2642,8 @@ int register_android_view_SurfaceControl(JNIEnv* env) GetFieldIDOrDie(env, dynamicInfoClazz, "activeDisplayModeId", "I"); gDynamicDisplayInfoClassInfo.renderFrameRate = GetFieldIDOrDie(env, dynamicInfoClazz, "renderFrameRate", "F"); + gDynamicDisplayInfoClassInfo.hasArrSupport = + GetFieldIDOrDie(env, dynamicInfoClazz, "hasArrSupport", "Z"); gDynamicDisplayInfoClassInfo.supportedColorModes = GetFieldIDOrDie(env, dynamicInfoClazz, "supportedColorModes", "[I"); gDynamicDisplayInfoClassInfo.activeColorMode = diff --git a/core/jni/platform/host/HostRuntime.cpp b/core/jni/platform/host/HostRuntime.cpp index 06621c9e6ab37871ad01ed21e25be0caba61ed1e..24551a4956a7c82550a4f377bbee0bda320ea4e6 100644 --- a/core/jni/platform/host/HostRuntime.cpp +++ b/core/jni/platform/host/HostRuntime.cpp @@ -120,6 +120,7 @@ static const std::unordered_map gRegJNIMap = { #endif {"android.content.res.StringBlock", REG_JNI(register_android_content_StringBlock)}, {"android.content.res.XmlBlock", REG_JNI(register_android_content_XmlBlock)}, +#ifdef __linux__ {"android.database.CursorWindow", REG_JNI(register_android_database_CursorWindow)}, {"android.database.sqlite.SQLiteConnection", REG_JNI(register_android_database_SQLiteConnection)}, @@ -127,7 +128,6 @@ static const std::unordered_map gRegJNIMap = { {"android.database.sqlite.SQLiteDebug", REG_JNI(register_android_database_SQLiteDebug)}, {"android.database.sqlite.SQLiteRawStatement", REG_JNI(register_android_database_SQLiteRawStatement)}, -#ifdef __linux__ {"android.os.Binder", REG_JNI(register_android_os_Binder)}, {"android.os.FileObserver", REG_JNI(register_android_os_FileObserver)}, {"android.os.MessageQueue", REG_JNI(register_android_os_MessageQueue)}, @@ -262,7 +262,8 @@ static void* mmapFile(const char* dataFilePath) { } // returns result from java.lang.System.getProperty -static string getJavaProperty(JNIEnv* env, const char* property_name) { +static string getJavaProperty(JNIEnv* env, const char* property_name, + const char* defaultValue = "") { jclass system = FindClassOrDie(env, "java/lang/System"); jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty", @@ -270,7 +271,7 @@ static string getJavaProperty(JNIEnv* env, const char* property_name) { auto jString = (jstring)env->CallStaticObjectMethod(system, getPropertyMethod, env->NewStringUTF(property_name), - env->NewStringUTF("")); + env->NewStringUTF(defaultValue)); ScopedUtfChars chars(env, jString); return string(chars.c_str()); } @@ -430,7 +431,6 @@ public: } // namespace android -#ifndef _WIN32 using namespace android; JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { @@ -439,12 +439,14 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { return JNI_ERR; } - Vector args; - HostRuntime runtime; + string useBaseHostRuntime = getJavaProperty(env, "use_base_native_hostruntime", "true"); + if (useBaseHostRuntime == "true") { + Vector args; + HostRuntime runtime; - runtime.onVmCreated(env); - runtime.start("HostRuntime", args, false); + runtime.onVmCreated(env); + runtime.start("HostRuntime", args, false); + } return JNI_VERSION_1_6; } -#endif diff --git a/core/proto/android/app/OWNERS b/core/proto/android/app/OWNERS index a137ea97b3a4b0eb47c8e650ad9cea7d7c1e55c8..519bf9a7fa4b3484bf90d78169b6f93713b504a8 100644 --- a/core/proto/android/app/OWNERS +++ b/core/proto/android/app/OWNERS @@ -1,3 +1,3 @@ -per-file appstartinfo.proto = file:/services/core/java/com/android/server/am/OWNERS +per-file appstartinfo.proto = file:/PERFORMANCE_OWNERS per-file location_time_zone_manager.proto = file:platform/frameworks/base:/services/core/java/com/android/server/timezonedetector/OWNERS per-file time_zone_detector.proto = file:platform/frameworks/base:/services/core/java/com/android/server/timezonedetector/OWNERS diff --git a/core/res/Android.bp b/core/res/Android.bp index 17d7bfa40f9059ba425b2f895b3fcfff1af6aec8..aa324fcaca58de861851d5c71c0ba0d75ff9cc79 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -167,6 +167,7 @@ android_app { "android.os.flags-aconfig", "android.os.vibrator.flags-aconfig", "android.media.tv.flags-aconfig", + "android.security.flags-aconfig", "com.android.hardware.input.input-aconfig", ], } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5693d666adc2cd381ffe6d64504afa843740b865..6ab64768d9f0dac16940d5ecdab47879e9f2549d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -852,6 +852,7 @@ + @@ -4105,6 +4106,24 @@ android:protectionLevel="signature|installer" /> + + + + + + + + + + + diff --git a/core/res/OWNERS b/core/res/OWNERS index d109cee5d910de6e47279c0c2d1e2027c2f6f34e..faed4d80f39bece872bd876c1c9c1046984434a3 100644 --- a/core/res/OWNERS +++ b/core/res/OWNERS @@ -53,7 +53,7 @@ per-file res/values/config_battery_saver.xml = file:/services/core/java/com/andr per-file res/values/dimens_car.xml = file:/platform/packages/services/Car:/OWNERS # Device Idle -per-file res/values/config_device_idle.xml = file:/apex/jobscheduler/OWNERS +per-file res/values/config_device_idle.xml = file:/apex/jobscheduler/DEVICE_IDLE_OWNERS # Display Manager per-file res/values/config_display.xml = file:/services/core/java/com/android/server/display/OWNERS diff --git a/core/res/res/drawable/ic_zen_mode_icon_piano.xml b/core/res/res/drawable/ic_zen_mode_icon_piano.xml new file mode 100644 index 0000000000000000000000000000000000000000..012b9398d687f6bc26b0218808a75d20b5390a2f --- /dev/null +++ b/core/res/res/drawable/ic_zen_mode_icon_piano.xml @@ -0,0 +1,25 @@ + + + + \ No newline at end of file diff --git a/core/res/res/drawable/notification_progress.xml b/core/res/res/drawable/notification_progress.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a6b60077045db0e3f2fba0e253c891fefc77512 --- /dev/null +++ b/core/res/res/drawable/notification_progress.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + diff --git a/core/res/res/layout/notification_template_material_progress.xml b/core/res/res/layout/notification_template_material_progress.xml index fdcefccdbf1658ca07c53bf6169970815f18f0b2..75827a279ff754e76f9eb4d8ab9dceee811ae227 100644 --- a/core/res/res/layout/notification_template_material_progress.xml +++ b/core/res/res/layout/notification_template_material_progress.xml @@ -75,12 +75,11 @@ /> - - - + android:layout_height="@dimen/notification_progress_tracker_height" + style="@style/Widget.Material.Notification.NotificationProgressBar" + /> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 8f4fbcd76939f6e1847e4b31660f1615781632fc..9323276c2d5a25b5a61707cbe79a50de23aca4ed 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -2122,7 +2122,7 @@ "לא ניתן היה לשחזר את קיצור הדרך עקב חוסר התאמה בחתימה על האפליקציות" "לא ניתן היה לשחזר את קיצור הדרך" "מקש הקיצור מושבת" - "הסרת התקנה" + "הסרה" "לפתוח בכל זאת" "אותרה אפליקציה מזיקה" "%1$s רוצה להציג חלקים מ-%2$s" diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 8a2d767e9ad15806682c3d196029558e07dcb975..41981715a8555688a1e2d5e28d00f3f07bfee001 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -287,6 +287,11 @@ vibration params. --> 50 + + 25 + @@ -4447,17 +4452,25 @@ - + false - - 0 + + 62914560 + + + 83886080 - + false - - 0 + + 62914560 + + + 20971520 - + + + + diff --git a/core/res/res/values/config_battery_stats.xml b/core/res/res/values/config_battery_stats.xml index 80cf0881e8ccaaa65689a2988ed0fdcb59808b46..9498273e17e09902c09220ecc68da054330083ab 100644 --- a/core/res/res/values/config_battery_stats.xml +++ b/core/res/res/values/config_battery_stats.xml @@ -45,7 +45,12 @@ 14400000 3600000 + + + 32768 + diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index b92aa2f355ed6f7161bd5e1c702b4507aab6a5b5..7184d9a8c8908edc3aadafa4bd0c698b03dada5d 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -817,6 +817,22 @@ 40dp 20dp + + 2dp + + 4dp + + 9dp + + 3dp + + 6dp + + 10dp + + 4dp + + 0dp @dimen/notification_small_icon_size diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index eec6ae3fb521f633278244dee7893c5e7732adc3..cb8e4aa9b2a9a9d2752d90d8a801e3cbeaa6a0e2 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -502,6 +502,10 @@ please see styles_device_defaults.xml. + - \ No newline at end of file + + + + diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/themes.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/themes.xml index 9ecc297c6d365ba778ed54c919357c46ead20985..403931764d7ea41e96a4c9ad84c8cdd4bf9756b7 100644 --- a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/themes.xml +++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/themes.xml @@ -21,4 +21,15 @@ @color/settingslib_primary_device_default_settings_light @color/settingslib_accent_device_default_light - \ No newline at end of file + + + + diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/themes_bridge.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/themes_bridge.xml new file mode 100644 index 0000000000000000000000000000000000000000..bcb9baf9470641636762550ed32afda0aa9ff77d --- /dev/null +++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/themes_bridge.xml @@ -0,0 +1,176 @@ + + + + + + + + + + + +